ScriptWhitelistGuard
Interactive PowerShell script execution guard with SHA256 whitelist verification
ScriptWhitelistGuard is a PowerShell module that intercepts external .ps1 script execution at the PSReadLine level, validates scripts against a SHA256-based whitelist, and transparently rewrites approved commands to execute with -ExecutionPolicy Bypass. It's designed as a workflow safety tool, not a security boundary.
๐ฏ What Does It Do?
When you type a command like npm -v or .\my-script.ps1 args... and press Enter:
- Intercepts the command before execution (via PSReadLine Enter key handler)
- Detects if it's an external PowerShell script (
.ps1) - Validates the script against your whitelist using SHA256 hash
- Allows execution by transparently rewriting to:
pwsh -NoProfile -ExecutionPolicy Bypass -File "script.ps1" args... - Blocks execution if not whitelisted or hash mismatch, displaying a helpful error with the exact command to whitelist it
How It Works
User Input: npm -v
โ
[PSReadLine Enter Handler]
โ
Resolve command โ C:\Program Files\nodejs\npm.ps1
โ
Check whitelist & SHA256 hash
โ
โ Match? โ Rewrite: & "pwsh" -NoProfile -ExecutionPolicy Bypass -File "C:\...\npm.ps1" -v
โ No match? โ Block & show: Add-ScriptWhitelist -Path "C:\...\npm.ps1"
๐ Quick Start
Installation
# From PowerShell Gallery (recommended) Install-Module -Name ScriptWhitelistGuard -Scope CurrentUser # Or clone and import manually git clone https://github.com/YourOrg/ScriptWhitelistGuard Import-Module ./ScriptWhitelistGuard/src/ScriptWhitelistGuard.psd1
Enable for Current Session
Import-Module ScriptWhitelistGuard Enable-WhitelistGuard
Enable Permanently (Auto-Start on All New Sessions)
Enable-WhitelistGuard -Persist
This adds an auto-enable block to your PowerShell profile ($PROFILE.CurrentUserAllHosts). From now on, every new PowerShell window will automatically activate the guard.
Disable Permanently
Disable-WhitelistGuard -Unpersist
๐ Whitelist Management
Add a Script to Whitelist
# Example: Whitelist Node.js npm script Add-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1" # Output: # โ Added to whitelist: C:\Program Files\nodejs\npm.ps1 # SHA256: a1b2c3d4e5f6...
Test If Script Is Whitelisted
Test-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1" # Returns: True or False
List All Whitelisted Scripts
Get-ScriptWhitelist # Output: # Path Sha256 AddedAt Exists # ---- ------ ------- ------ # C:\Program Files\nodejs\npm.ps1 a1b2c3d4e5f6... 2026-01-29T10:30:00Z True
Remove from Whitelist
Remove-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1"
Repair/Update Hash After Script Changes
# When a script is updated (e.g., Node.js upgrade), its hash changes # Update the whitelist entry: Repair-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1" # Equivalent to: Add-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1"
๐ง Common Scenarios
Scenario 1: First Time Running npm
PS> npm -v โ Script execution blocked by ScriptWhitelistGuard Script: C:\Program Files\nodejs\npm.ps1 Reason: Script not in whitelist To allow this script, run: Add-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1" PS> Add-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1" โ Added to whitelist: C:\Program Files\nodejs\npm.ps1 SHA256: a1b2c3d4e5f6... PS> npm -v 10.2.4
Scenario 2: Node.js Update Breaks npm
After updating Node.js, the npm.ps1 script changes, causing a hash mismatch:
PS> npm -v โ Script execution blocked by ScriptWhitelistGuard Script: C:\Program Files\nodejs\npm.ps1 Reason: SHA256 hash mismatch (script has been modified) To allow this script, run: Add-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1" PS> Repair-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1" โ Added to whitelist: C:\Program Files\nodejs\npm.ps1 SHA256: z9y8x7w6v5u4... PS> npm -v 11.0.0
Scenario 3: Custom Whitelist Storage Location
Use an environment variable to store the whitelist in a custom location (e.g., for team-shared whitelists):
# Set before importing the module $env:SCRIPT_WHITELIST_GUARD_STORE = "C:\TeamConfig\shared-whitelist.json" Import-Module ScriptWhitelistGuard Enable-WhitelistGuard
โ๏ธ Advanced Configuration
Custom Whitelist Storage Path
By default, the whitelist is stored at $HOME\.ps-script-whitelist.json. To use a custom path:
$env:SCRIPT_WHITELIST_GUARD_STORE = "D:\MyConfig\whitelist.json"
Set this environment variable before importing the module or add it to your profile.
Profile Persistence Details
When you run Enable-WhitelistGuard -Persist, the module adds the following block to your profile:
# BEGIN ScriptWhitelistGuard Auto-Enable Import-Module ScriptWhitelistGuard -ErrorAction SilentlyContinue if (Get-Module -Name ScriptWhitelistGuard) { Enable-WhitelistGuard } # END ScriptWhitelistGuard Auto-Enable
- Idempotent: Running
-Persistmultiple times won't create duplicate blocks - Safe Removal:
Disable-WhitelistGuard -Unpersistremoves only this block, preserving your other profile content
๐ก๏ธ Security & Limitations
โ ๏ธ NOT A SECURITY BOUNDARY
Important: This module is not a security feature and can be easily bypassed:
- Any user can run
powershell -ExecutionPolicy Bypass -File script.ps1directly - The guard only intercepts interactive PSReadLine input (not scripts, scheduled tasks, or CI/CD)
- Users with profile write access can disable it with
Disable-WhitelistGuard -Unpersist - It's designed for workflow safety (prevent accidental execution of untrusted scripts), not malware prevention
For True Enforcement
If you need genuine script execution control:
- Windows: Use AppLocker or Windows Defender Application Control (WDAC)
- Enterprise: Implement GPO-based execution policies
- Code Signing: Require signed scripts with trusted certificates
ScriptWhitelistGuard is a convenience tool, not a replacement for these security measures.
๐ What Gets Intercepted?
Intercepted (External .ps1 Scripts)
- โ
npm -v(resolves tonpm.ps1) - โ
.\my-script.ps1 - โ
C:\Scripts\build.ps1 -Verbose
NOT Intercepted
- โ Built-in cmdlets:
Get-Process,Set-Location - โ Functions defined in your session
- โ Aliases:
ls,dir,gci - โ Executables:
node,python.exe,git - โ Non-interactive execution: scripts run via Task Scheduler, CI/CD pipelines
- โ Commands pasted or run programmatically (not typed interactively)
๐ฆ Exported Commands
| Command | Description |
|---|---|
Add-ScriptWhitelist |
Add or update a script in the whitelist with its current SHA256 hash |
Remove-ScriptWhitelist |
Remove a script from the whitelist |
Test-ScriptWhitelist |
Check if a script is whitelisted and hash matches |
Get-ScriptWhitelist |
List all whitelisted scripts with metadata |
Repair-ScriptWhitelist |
Update the hash for an existing whitelisted script (alias for Add) |
Enable-WhitelistGuard |
Activate the guard for the current session (use -Persist for auto-enable) |
Disable-WhitelistGuard |
Deactivate the guard (use -Unpersist to remove from profile) |
๐งช Testing
Run Pester tests locally:
# Install Pester if needed Install-Module Pester -MinimumVersion 5.0.0 -Force # Run tests Invoke-Pester -Path ./tests
๐ค Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes with tests
- Ensure CI passes:
Invoke-PesterandInvoke-ScriptAnalyzer - Submit a pull request
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Related Projects
- PSReadLine - Command-line editing for PowerShell
- PowerShell Execution Policies
Made with โค๏ธ for the PowerShell community