Open-source project
techspence/ScriptSentry avatar
techspence/ScriptSentry

ScriptSentry: auditing logon scripts in Active Directory

ScriptSentry finds misconfigured and dangerous logon scripts.

676 stars56 forksPowerShellNOASSERTION

At a glance

What is it?
ScriptSentry is a single PowerShell file that enumerates logon scripts across a domain and reports the ones that are dangerous, covering plaintext credentials, unsafe permissions on the shares they touch, logon scripts assigned to administrators and references to shares that no longer exist. It is a defensive audit tool, and it is deliberately a one-liner invocation rather than a framework.
Who is it for?
ScriptSentry suits a Windows administrator doing an Active Directory hygiene pass, who wants the logon script picture in one pass rather than by exporting and reading every GPO by hand. It is the wrong tool if you need continuous monitoring, since it is a point-in-time audit script with no scheduling or reporting layer of its own, and it is the wrong tool if your problem is Group Policy design rather than the scripts it points at.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 36 days ago.
What is it written in?
Mainly PowerShell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem is the script nobody reviews

ScriptSentry finds misconfigured and dangerous logon scripts, and the word logon here means the batch or PowerShell file that a user gets run when they log on to a domain machine, usually delivered through Group Policy from the NETLOGON share or from SYSVOL. These files are an old and unlovely corner of enterprise Windows, and they accumulate. Someone writes a net use command with a service account password in it, someone points a logon script at a file share that an administrator later deletes, and nobody looks at either again because the script still runs fine for the person who wrote it. The audience for this tool is a Windows administrator or a security engineer doing an Active Directory hygiene pass, typically after a penetration test finding or during a hardening project. The value is coverage, since a manual review of every GPO logon script in a large domain is slow and easy to do incompletely, and the reports are written to be read rather than exported for further analysis.

The findings are grouped into named misconfigurations

The console output is organised by category, and each finding carries an identifier and a description. The categories in the sample output are plaintext credentials, unsafe UNC folder permissions, unsafe UNC file permissions, unsafe NETLOGON and SYSVOL permissions, unsafe logon script permissions, unsafe GPO logon script permissions, admins with logon scripts, nonexistent shares, and admins with logon scripts mapped from a nonexistent share. The identifiers follow the same scheme, with LSM-Creds for the credential finding, LSM-Access-1 through LSM-Access-5 for the permission findings, LSM-Admins-1 and LSM-Admins-2 for the administrator findings and LSM-Shares for the missing share finding. That naming is worth a moment, because it is what makes the output actionable. A report that says a share is writable by domain users is an observation. A report that says unsafe NETLOGON and SYSVOL permissions, with the exact path, is a ticket. The tool also pairs the permission findings with the specific artefact that is misconfigured, so the UNC folder, the UNC file, the NETLOGON path, the logon script path and the GPO logon script are each reported separately rather than collapsed into one finding about the domain.

Plaintext credentials are reported with the secret removed

The first category is the one that gets attention. The sample output shows a logon script at a sysvol path containing a net use command that maps a drive letter to a file server with a user and a service account name, and the credential itself is printed as redacted. So the finding tells you both things you need. The password is not echoed into your terminal, and probably not into whatever is capturing your terminal when you paste the output into a ticket, but the account name and the target share are. That combination is what makes the finding useful rather than dangerous, since the account name tells you which credential to rotate and the share tells you which script to fix. The detection is aimed at the classic pattern of a batch file embedding a password so that a mapping exists for the user session. It is worth noting what the tool does not claim: the README does not document heuristics for obfuscated or encoded credentials, so the safest assumption is that it looks for the visible pattern rather than trying to defeat encoding.

Permission checks follow the path in the script

The four access findings are about who can change the files, and the ordering shows that the tool works along the chain of references rather than testing one location. First the UNC folder that the logon script points at, then the file inside it, then the NETLOGON share itself, then the logon script file, and finally the Group Policy logon script. Each is checked for Modify permission for the domain users group, and each is reported with the full path, so the sample output shows domain users with Modify on a tools share, on a startup script inside it, on the NETLOGON share of the domain, on the logon script in SYSVOL, and on a logon script in NETLOGON. The reasoning behind checking the same weakness five times is that fixing one of them is pointless if the other four still allow the same write, and because a script is only as trustworthy as the most permissive path that reaches it.

Running it: one file, a few switches

The usage section is short because the tool is one PowerShell file, Invoke-ScriptSentry.ps1, that you run from memory. The documented invocations cover the console, saving to a text file, saving results as a CSV in the current directory, saving to a chosen directory, using alternate credentials, and targeting a specific domain controller:

powershell
# Run ScriptSentry and display results on the console
IEX(Invoke-WebRequest 'https://raw.githubusercontent.com/techspence/ScriptSentry/main/Invoke-ScriptSentry.ps1')
Invoke-ScriptSentry

# Run ScriptSentry and save output to a text file
IEX(Invoke-WebRequest 'https://raw.githubusercontent.com/techspence/ScriptSentry/main/Invoke-ScriptSentry.ps1')
Invoke-ScriptSentry | Out-File c:\temp\ScriptSentry.txt

The CSV route uses the SaveOutput switch, with an OutputDirectory parameter for a specific path, and the credential route takes a PSCredential from Get-Credential. One rule is stated explicitly and it matters in practice: the Server and Domain parameters must be used together, so you cannot point at a domain controller without naming its domain. Another is worth internalising before a first run, because it defines the blast radius of what you will see. The Credential parameter applies to the LDAP queries, while SYSVOL, NETLOGON and other UNC paths are accessed as the user running PowerShell. So an audit run with different LDAP credentials still reads the file shares with your own rights, and any share your account cannot read will not appear in the report.

The invocation pattern is the weak point

There is a design decision here worth arguing with. The recommended way to run the tool is to fetch it from a URL and execute it in memory with IEX(Invoke-WebRequest ...), which means the script never touches disk and there is nothing to review, sign or pin before it runs. That is convenient, and it is also exactly the pattern that security teams warn about when a vendor asks you to pipe a script from the internet into your shell. The counter-argument is that the repository is a single file, so the alternative is trivial. You can download Invoke-ScriptSentry.ps1, read it, and run it, and the repository is small enough that reading it is a five minute job rather than a project. The tool does not publish releases, so there is no tag to pin, and the script sits on the main branch, which means the content at that URL can change. If you are going to run this against a domain, downloading the file and reviewing it first is the difference between auditing your directory and letting someone else decide what your directory looks like.

A one file repository, and an unclassified licence

The repository is as small as it sounds. The top level holds a .gitignore, the Invoke-ScriptSentry.ps1 script, the LICENSE file, the README and a screenshot, so there is no module, no installer, no configuration file and no dependency to manage. The project is written in PowerShell, which is the same language the domain administrators it targets already have, and that is the reason there is nothing else to install. The documentation points to a blog post on offsec.blog about identifying misconfigured and dangerous logon scripts, which is where the method behind the checks is written up. Two loose ends remain for anyone who wants to use this formally. The repository licence field is classified as a custom licence that GitHub cannot categorise, so the LICENSE file is the text that governs and it should be read before the output of an audit is shared or redistributed. And the project publishes no GitHub releases, so there is no version to pin, with the last push to the main branch on 2026-09-17 being the only reference point for how current the code is.

Editorial conclusion

ScriptSentry suits a Windows administrator doing an Active Directory hygiene pass, who wants the logon script picture in one pass rather than by exporting and reading every GPO by hand. It is the wrong tool if you need continuous monitoring, since it is a point-in-time audit script with no scheduling or reporting layer of its own, and it is the wrong tool if your problem is Group Policy design rather than the scripts it points at. Before running it in a production domain, check the licence file in the repository, and remember that the SYSVOL, NETLOGON and other UNC paths are read as the account running PowerShell, so the tool sees exactly what that account can see and nothing more.

Frequently asked questions

How do I run ScriptSentry against a domain?

The documented usage fetches Invoke-ScriptSentry.ps1 with IEX(Invoke-WebRequest ...) and then calls Invoke-ScriptSentry. You can save the output to a text file with Out-File, or use the SaveOutput switch to write results as a CSV, optionally with an OutputDirectory parameter.

What kinds of problems does ScriptSentry report?

Plaintext credentials inside a logon script, unsafe UNC folder, file, NETLOGON, SYSVOL and GPO logon script permissions, logon scripts assigned to administrators, references to shares that do not exist, and administrator logon scripts mapped from a nonexistent share. Findings carry identifiers such as LSM-Creds, LSM-Access-1 to LSM-Access-5, LSM-Admins-1, LSM-Admins-2 and LSM-Shares.

Can I use different credentials for the queries?

Yes, the Credential parameter takes a PSCredential and applies to the LDAP queries, while SYSVOL, NETLOGON and other UNC paths are accessed as the user running PowerShell. The Server and Domain parameters must be used together, so you cannot target a domain controller without naming its domain.

Is the credential found in a logon script printed in the output?

In the sample output the credential itself appears as redacted, while the account name and the target share are shown. The README does not describe any handling of encoded or obfuscated credentials, so the detection is best understood as looking for the visible pattern.

Official sources

  1. Issues
  2. Project website
  3. README
  4. techspence/ScriptSentry on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/techspence-scriptsentry.svg)](https://hysenlabs.com/projects/techspence-scriptsentry)

Was this useful?