What AD logon script paths mean
AD logon script paths deserve an inventory and ownership review before anyone changes permissions. A populated user attribute tells you where a logon script is configured; it does not tell you whether the target exists, whether anyone still uses it, or who can change its contents. Treat the path as the starting point for evidence collection.
Microsoft's Script-Path schema reference identifies scriptPath as the user's logon-script path and allows a null string. The New-ADUser ScriptPath parameter accepts a local absolute path or a Universal Naming Convention (UNC) path. A UNC value is therefore a documented configuration option. Its presence alone does not establish weak access control.
The useful questions are concrete: which user points to which target, who owns the business function, which clients consume it, and which principals can modify that target? The account owner, script maintainer, and file-server administrator may be different people. Record each responsibility rather than assuming that the filesystem owner also approves the business use.
How It Works: distinguish assignment, content and use
The review has three layers. The directory attribute assigns a path. The referenced file and its dependencies contain the instructions. The client's actual logon behavior determines whether those instructions are used. Evidence from one layer cannot stand in for the others.
MITRE ATT&CK's Network Logon Script technique describes abuse of scripts assigned through Active Directory or Group Policy and recommends limiting their writers to designated administrators. It describes execution with the assigned user's privileges. Do not infer SYSTEM execution from a network-path finding. To investigate possible abuse, establish an unauthorized ability to alter the script or redirect its assignment, then establish that a relevant client consumes the changed content. This article does not claim that either event occurred.
Keep user scriptPath separate from scripts configured inside a GPO. If policy deployment is involved, use the separate GPO Read, Apply and scope review. Its computer-Read and targeted-Apply questions concern policy retrieval and application; they do not establish who can rewrite the file referenced by a user's attribute.
Also inspect the content for dependencies and exposed credentials through the appropriate review process. The existing review of credentials in SYSVOL files, including scripts covers that concern. A path inventory cannot establish whether a script contains a secret, and this workflow does not repeat the separate cPassword investigation.
Detection: inventory users, resolve targets, inspect both ACLs
1. Inventory configured paths without dropping disabled users
Run the following examples from an authorized Windows administrative environment with the relevant modules. They are documentation-based examples, not commands executed against a customer domain. Replace the example server, search base, identities and paths with approved values.
The Get-ADUser reference documents -LDAPFilter, -SearchBase, -Server, and retrieval of additional attributes with -Properties. This query inventories users with scriptPath present, including disabled accounts:
Get-ADUser -LDAPFilter '(scriptPath=*)' -SearchBase 'DC=example,DC=com' -Server 'dc01.example.com' -Properties scriptPath | Format-List -Property DistinguishedName,SamAccountName,Enabled,scriptPath
An alternative using the module's filter syntax is:
Get-ADUser -Filter 'scriptPath -like "*"' -SearchBase 'DC=example,DC=com' -Server 'dc01.example.com' -Properties scriptPath | Format-List -Property DistinguishedName,SamAccountName,Enabled,scriptPath
The attribute-presence pattern adapts Microsoft's Active Directory filter examples. Format-List displays named properties; retain the underlying inventory in your approved evidence system as well. Record the queried domain controller, search base, collection time and any errors. A partial or failed query is not a complete inventory.
Join each user to the path and a responsible owner. Keep disabled accounts visible as lifecycle cases: ask whether the assignment is retained for a planned return, copied from a template, or obsolete. Do not enable an account to test its script. A disabled user's assignment does not establish current use; it can still identify a target shared with other users.
2. Resolve the target in the real client context
Preserve the literal attribute before interpreting it. For a relative string, identify its resolution base on the relevant client and logon workflow; do not resolve it against your administrative shell's working directory. For a local absolute path, identify the client on which that file should exist. For a network path, identify the actual server, share and file reached by the test client. Record unresolved cases explicitly.
Ask the maintainer which scripts, executables, configuration files or other resources the entry point depends on. Review those targets too. Changing the entry point's ACL alone is insufficient if an unreviewed dependency supplies the instructions the script consumes.
After resolving a candidate file, this example uses documented Test-Path parameters:
Test-Path -LiteralPath '\\files01.example.com\LogonScripts\onboarding.cmd' -PathType Leaf
Leaf tests for a file-like endpoint; -LiteralPath avoids wildcard interpretation. Record the identity, client and errors with the result. This existence test does not prove successful logon execution, script correctness, or permission to modify the file. Confirm actual use through an approved pilot with the script owner.
3. Inspect share and filesystem permissions independently
On the identified file server, use Get-SmbShare to map the share name to its local path. Then use Get-SmbShareAccess to retrieve its share ACL. These examples adapt the documented -Name queries:
Get-SmbShare -Name 'LogonScripts' | Format-List -Property Name,ScopeName,Path
Get-SmbShareAccess -Name 'LogonScripts'
Run these on the actual hosting server. If a scoped share is involved, identify its scope and use the documented -ScopeName parameter. A similarly named share on another server is not evidence for this target. Preserve each trustee, Allow or Deny entry, and access level.
For NTFS, Get-Acl retrieves the resource's security descriptor on Windows. After confirming the real local path, inspect the file and its containing directory:
Get-Acl -LiteralPath 'D:\LogonScripts\onboarding.cmd' | Format-List -Property *
Get-Acl -LiteralPath 'D:\LogonScripts' | Format-List -Property *
These are examples, not an assertion that this share maps to D:\LogonScripts. Capture ownership, access entries and inheritance. Resolve the groups behind each trustee before concluding which users can change the content. The ACL listing is evidence for that review, not an effective-access simulation for every identity.
Microsoft's file security model evaluates requested rights against the caller's token and the object's descriptor. Its file access-rights constants distinguish writing file data, creating files in a directory, and deleting children. Review the ability to alter or replace content as well as permission administration; reading the script is a different question. Inspect share and NTFS evidence together for the specific access route.
| Evidence | Decision it supports | What remains unproved |
|---|---|---|
User and populated scriptPath | Which assignments to review | Target existence, ACLs and use |
| Resolved file and existence test | Which resource was reached from that context | Successful script execution |
| Share and NTFS descriptors | Which grants and trustees need analysis | Every user's effective access |
| Owner-approved client test | Whether the expected workflow worked in that test | Behavior across untested clients |
Remediation: review first, then make a targeted correction
1. Agree the intended behavior and writers
For each assignment, record the business owner, expected client population, approved maintainers and necessary read access. Classify it as required, obsolete, or unresolved. Keep uncertainty visible rather than treating it as permission to delete. A shared target can have multiple consumers, so coordinate its change with every affected owner.
2. Preserve a rollback state and pilot the change
Preserve the current attribute, target content, dependencies and both permission sets using your approved backup process. Choose a representative enabled test user and client. Define the expected outcome and failure conditions before the pilot. For disabled accounts, use a lifecycle decision instead of a forced logon test.
3. Correct the verified problem at its source
If the target is required but an unintended principal can change it, have the file-server owner correct the specific share or NTFS grant through the approved change procedure. Review inherited grants and dependencies before selecting the change. MITRE's mitigation supports restricting script writers; it does not prescribe one universal ACL for every environment.
If the assignment points to a wrong target, change that user's attribute only after validating the replacement. The following preview uses the documented Set-ADUser ScriptPath and WhatIf parameters:
Set-ADUser -Identity 'CN=PilotUser,OU=Users,DC=example,DC=com' -Server 'dc01.example.com' -ScriptPath '\\files01.example.com\LogonScripts\approved.cmd' -WhatIf
-WhatIf previews the operation without applying it. This command is an option for an approved assignment correction, not a recommendation to migrate all users to UNC paths. If an assignment is obsolete, retire it through the agreed account-management procedure after checking shared dependencies. Do not delete a referenced file merely because one user no longer needs it.
4. Re-read configuration and verify authorized behavior
Re-query the exact user after the approved change:
Get-ADUser -Identity 'CN=PilotUser,OU=Users,DC=example,DC=com' -Server 'dc01.example.com' -Properties scriptPath | Format-List -Property DistinguishedName,Enabled,scriptPath
Re-read both ACLs if permissions changed. Repeat the owner-approved client test and validate required retrieval and expected behavior. Where appropriate, verify that an unintended writer lacks effective modification access using the organization's authorized access-testing procedure. Keep the test context, results, exceptions and rollback decision with the inventory. Attribute re-reading alone cannot validate the script's effects.
How EtcSec Detects This
EtcSec's DANGEROUS_LOGON_SCRIPTS check supplies a review list. In etc-collector commit 15fc6399c215eabc415c370b762303cfcd7a353a, dangerous-logon-scripts.go:46 iterates supplied users and selects a nonempty ScriptPath when it contains two consecutive backslashes anywhere, or starts with //. It does not require a strict UNC prefix in the backslash branch. The finding is Medium, and Count is the number of matching users, not distinct files or vulnerable shares.
There is no Disabled filter in this Detect(). Disabled users can therefore appear when supplied in the audit data. An empty path does not match; relative paths and other strings outside the predicate can escape this review list. Conversely, a matching string does not establish a valid, reachable UNC target.
The LDAP provider requests scriptPath in parser.go:49, copies it into ScriptPath at parser.go:171, and retrieves users through client.go:460. This check does not read the target file, share ACL, NTFS ACL, or effective execution. Its output cannot confirm unauthorized write access, successful persistence, or SYSTEM execution. Collection scope and completeness also limit what the list represents.
Explore the identity security pages that support this topic
