Last active
May 28, 2026 11:14
-
-
Save raysubham/5330119da4d1b886461f3846fd22d330 to your computer and use it in GitHub Desktop.
StepSecurity Dev Machine Guard - Windows uninstall script. Cleans agent binary, launcher, loader, scheduled task, ProgramData config + logs, and per-user .stepsecurity dir. See https://github.com/step-security/dev-machine-guard
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #Requires -Version 5.1 | |
| <# | |
| .SYNOPSIS | |
| Uninstalls StepSecurity Dev Machine Guard from a Windows endpoint. | |
| .DESCRIPTION | |
| Production uninstall delivered via Intune Platform Script (or manual | |
| elevated RDP run). Cleans both install layouts produced by the | |
| PowerShell loader: | |
| Elevated (machine-wide): | |
| C:\Program Files\StepSecurity\ | |
| C:\ProgramData\StepSecurity\ | |
| Non-elevated (per-user, ALL user profiles on the box): | |
| C:\Users\*\.stepsecurity\ | |
| Also removes the scheduled task "StepSecurity Dev Machine Guard" and | |
| stops any running agent + launcher processes. | |
| Logs to %TEMP%\stepsecurity-uninstall.log (kept after uninstall - the | |
| ProgramData log location is itself removed). | |
| Exits non-zero if any tracked artifact survives, so Intune surfaces | |
| the failure in the portal. | |
| .PARAMETER LogPath | |
| Override the log file location. Defaults to | |
| %TEMP%\stepsecurity-uninstall.log. | |
| .NOTES | |
| Deploy as an Intune Platform Script with: | |
| Run as logged-on user : Yes (matches install elevation flow) | |
| Enforce signature check : No (script is unsigned in this repo) | |
| Run script in 64-bit host : Yes | |
| All strings are ASCII-only to survive PS 5.1 ANSI codepage parsing | |
| on non-BOM downloads. | |
| #> | |
| [CmdletBinding()] | |
| param( | |
| [string]$LogPath = (Join-Path $env:TEMP "stepsecurity-uninstall.log") | |
| ) | |
| $ErrorActionPreference = 'Continue' | |
| # Fail fast if not running elevated. C:\Program Files + ProgramData removal | |
| # and schtasks /delete all require admin token. PowerShell launched without | |
| # "Run as administrator" gets a UAC-filtered token even for local admins. | |
| $_principal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) | |
| if (-not $_principal.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)) { | |
| Write-Host "[FATAL] Run elevated. Right-click PowerShell -> Run as administrator, then rerun." -ForegroundColor Red | |
| exit 2 | |
| } | |
| $TASK_NAME = 'StepSecurity Dev Machine Guard' | |
| $PROCESS_NAMES = @( | |
| 'stepsecurity-dev-machine-guard', | |
| 'stepsecurity-dev-machine-guard-task' | |
| ) | |
| $MACHINE_DIRS = @( | |
| 'C:\Program Files\StepSecurity', | |
| 'C:\ProgramData\StepSecurity' | |
| ) | |
| function Get-UserProfileDirs { | |
| # Enumerate all user profile dirs under C:\Users. Skip system + service | |
| # accounts (Public, Default, Default User, All Users) which never hold | |
| # an interactive .stepsecurity install. | |
| $skip = @('Public', 'Default', 'Default User', 'All Users') | |
| Get-ChildItem -LiteralPath 'C:\Users' -Directory -ErrorAction SilentlyContinue | | |
| Where-Object { $skip -notcontains $_.Name } | | |
| ForEach-Object { Join-Path $_.FullName '.stepsecurity' } | |
| } | |
| function Write-Log { | |
| param([string]$Message, [string]$Level = 'INFO') | |
| $line = "[{0}] [{1}] {2}" -f (Get-Date -Format 'yyyy-MM-ddTHH:mm:ssK'), $Level, $Message | |
| Write-Host $line | |
| Add-Content -Path $LogPath -Value $line -ErrorAction SilentlyContinue | |
| } | |
| function Stop-AgentProcesses { | |
| foreach ($name in $PROCESS_NAMES) { | |
| $procs = Get-Process -Name $name -ErrorAction SilentlyContinue | |
| if ($procs) { | |
| Write-Log "Stopping process: $name ($($procs.Count) instance(s))" | |
| $procs | Stop-Process -Force -ErrorAction SilentlyContinue | |
| } | |
| } | |
| } | |
| function Invoke-AgentSelfUninstall { | |
| # Best-effort: let the agent run its own uninstall hooks before we | |
| # blow away the binary. Tolerates missing binary and non-zero exits. | |
| $candidates = @('C:\Program Files\StepSecurity\bin\stepsecurity-dev-machine-guard.exe') | |
| foreach ($u in Get-UserProfileDirs) { | |
| $candidates += (Join-Path $u 'bin\stepsecurity-dev-machine-guard.exe') | |
| } | |
| foreach ($exe in $candidates) { | |
| if (Test-Path -LiteralPath $exe) { | |
| Write-Log "Invoking agent self-uninstall: $exe uninstall" | |
| try { | |
| & $exe uninstall 2>&1 | ForEach-Object { Write-Log " $_" 'AGENT' } | |
| } catch { | |
| Write-Log "Agent self-uninstall threw: $($_.Exception.Message)" 'WARN' | |
| } | |
| } | |
| } | |
| } | |
| function Remove-ScheduledTask { | |
| & schtasks.exe /query /tn $TASK_NAME 2>&1 | Out-Null | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Log "Scheduled task '$TASK_NAME' not present" | |
| return | |
| } | |
| & schtasks.exe /delete /tn $TASK_NAME /f 2>&1 | ForEach-Object { Write-Log " $_" 'SCHTASKS' } | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Log "Removed scheduled task: $TASK_NAME" | |
| } else { | |
| Write-Log "Failed to remove scheduled task: $TASK_NAME (exit $LASTEXITCODE)" 'WARN' | |
| } | |
| } | |
| function Remove-Tree { | |
| param([string]$Path) | |
| if (-not (Test-Path -LiteralPath $Path)) { | |
| Write-Log "Not present: $Path" | |
| return | |
| } | |
| try { | |
| Remove-Item -LiteralPath $Path -Recurse -Force -ErrorAction Stop | |
| Write-Log "Removed: $Path" | |
| } catch { | |
| Write-Log "Failed to remove '$Path': $($_.Exception.Message)" 'WARN' | |
| } | |
| } | |
| function Assert-Clean { | |
| $residuals = @() | |
| foreach ($d in $MACHINE_DIRS) { | |
| if (Test-Path -LiteralPath $d) { $residuals += $d } | |
| } | |
| foreach ($u in Get-UserProfileDirs) { | |
| if (Test-Path -LiteralPath $u) { $residuals += $u } | |
| } | |
| & schtasks.exe /query /tn $TASK_NAME 2>&1 | Out-Null | |
| if ($LASTEXITCODE -eq 0) { $residuals += "scheduled task: $TASK_NAME" } | |
| return $residuals | |
| } | |
| # --- main ---------------------------------------------------------------- | |
| Write-Log "==== StepSecurity Dev Machine Guard uninstall ====" | |
| Write-Log "User: $env:USERNAME Computer: $env:COMPUTERNAME PSVersion: $($PSVersionTable.PSVersion)" | |
| Stop-AgentProcesses | |
| Invoke-AgentSelfUninstall | |
| Stop-AgentProcesses # second pass: self-uninstall may have spawned children | |
| Remove-ScheduledTask | |
| foreach ($d in $MACHINE_DIRS) { Remove-Tree -Path $d } | |
| foreach ($u in Get-UserProfileDirs) { Remove-Tree -Path $u } | |
| $residuals = Assert-Clean | |
| if ($residuals.Count -gt 0) { | |
| Write-Log "Residual artifacts after uninstall:" 'ERROR' | |
| foreach ($r in $residuals) { Write-Log " - $r" 'ERROR' } | |
| Write-Log "Uninstall FAILED. See $LogPath" 'ERROR' | |
| exit 1 | |
| } | |
| Write-Log "Uninstall complete - host is clean." | |
| exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment