Summary
Production incident involving a PowerShell script designed to send reboot alerts failing to execute during Windows startup. Despite successful manual execution, automated startup methods (Task Scheduler, .bat files, startup folder) didn’t trigger the script, causing delayed incident notifications.
Root Cause
Two primary technical failures:
- Contextual permission mismatch:
- Task Scheduler executed the script under
SYSTEMor a non-interactive user context lacking required privileges, whereas manual tests used interactive/admin sessions.
- Task Scheduler executed the script under
- PowerShell execution policy enforcement:
- Startup methods couldn’t bypass the PowerShell
Restrictedexecution policy that prevented script execution.
- Startup methods couldn’t bypass the PowerShell
Why This Happens in Real Systems
Three systemic patterns enable this failure:
- Non-interactive sessions block script execution by default due to security policies.
- Execution policies are scoped to users/processes, creating inconsistent behavior between manual/automated execution.
- Silent failure modes exist when scripts lack explicit startup logging, masking errors.
Real-World Impact
- Missed critical alerts during server reboots, delaying incident response.
- False confidence from manual tests not reflecting runtime environment conditions.
- Orphaned alerts due to missing startup dependencies (e.g., missing modules, network latency during boot).
Example or Code
Minimal Task Scheduler configuration to override execution policy and context:
# Executes script as LocalSystem with unrestricted permissions
$Trigger = New-ScheduledTaskTrigger -AtStartup
$Action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument `
"-NoProfile -ExecutionPolicy Bypass -File C:\Path\To\Script.ps1"
Register-ScheduledTask "RebootAlert" -Action $Action -Trigger $Trigger -User "NT AUTHORITY\SYSTEM" -RunLevel Highest
How Senior Engineers Fix It
- Explicitly define execution context:
- Validate and configure Task Scheduler to use
NT AUTHORITY\SYSTEMor a privileged account with script-specific permissions.
- Validate and configure Task Scheduler to use
- Override restrictive policies:
- Use
-ExecutionPolicy Bypassin PowerShell arguments to ignore safety locks.
- Use
- Add startup diagnostics:
- Embed logging (e.g.,
Start-Transcript) to capture silent failures.
- Embed logging (e.g.,
- Package dependencies:
- Deploy scripts/modules to
$env:ProgramFilesto avoid user-specific path issues.
- Deploy scripts/modules to
Why Juniors Miss It
- Assumption uniformity: Manual tests work → automated “should work,” ignoring context/security nuances.
- Insufficient debugging: Not testing scheduled tasks via
powershell.exe -Command "Get-ScheduledTask | gangsdebug"or checking Event Viewer logs. - Security policy gaps: Underestimating how PowerShell’s execution policy behaves across ], sessions and user accounts.
- Overlooking failure signatures: Silent errors (e.g., 0x1 exit code) dismissed without deeper investigation.