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.
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
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"
# 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.psd1Import-Module ScriptWhitelistGuard
Enable-WhitelistGuardEnable-WhitelistGuard -PersistThis adds an auto-enable block to your PowerShell profile ($PROFILE.CurrentUserAllHosts). From now on, every new PowerShell window will automatically activate the guard.
Disable-WhitelistGuard -Unpersist# 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-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1"
# Returns: True or FalseGet-ScriptWhitelist
# Output:
# Path Sha256 AddedAt Exists
# ---- ------ ------- ------
# C:\Program Files\nodejs\npm.ps1 a1b2c3d4e5f6... 2026-01-29T10:30:00Z TrueRemove-ScriptWhitelist -Path "C:\Program Files\nodejs\npm.ps1"# 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"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.4After 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.0Use 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-WhitelistGuardBy 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.
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
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
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.
- β
npm -v(resolves tonpm.ps1) - β
.\my-script.ps1 - β
C:\Scripts\build.ps1 -Verbose
- β 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)
| 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) |
Run Pester tests locally:
# Install Pester if needed
Install-Module Pester -MinimumVersion 5.0.0 -Force
# Run tests
Invoke-Pester -Path ./testsContributions 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
This project is licensed under the MIT License - see the LICENSE file for details.
- PSReadLine - Command-line editing for PowerShell
- PowerShell Execution Policies
Made with β€οΈ for the PowerShell community