Generate a bulk offboarding script with AI, then run the mandatory safety review — -WhatIf, least privilege, error paths, secrets, scoped filters, PSScriptAnalyzer — and separately risk-flag a legacy script whose two planted dangers, an unscoped Remove and a plaintext credential, have been waiting in production since 2019.
Meera inherited the sysadmin seat at a Hyderabad logistics firm along with a scripts folder nobody can explain. The previous admin left; his automations did not. This week she has two jobs: build a proper bulk-offboarding script for the quarterly contractor exit — with AI doing the drafting — and decide whether offboard_old.ps1, which has run unattended every Friday for seven years, is safe to keep. The research this track is built on found that 100% of studied AI-generated admin scripts contained exploitable flaws. The review protocol is therefore not a formality. It is the skill.
Nothing in this lab runs against a real directory. You will review, harden and dry-run — the discipline transfers; the blast radius does not.
~75 minutes hands-on · Core tier (maps to module M4). $0 — any free AI chat, PowerShell 7 (or Windows PowerShell 5.1), and PSScriptAnalyzer (Install-Module PSScriptAnalyzer -Scope CurrentUser, free). A throwaway VM is nice but optional — no step here executes destructive code.
Save the block below as offboard_old.ps1. This is a condensed excerpt of the 300-line legacy script — the sections that matter are intact and unmodified. Do not run it. Two of its behaviors are dangerous enough to have deleted this company's file server, and part of your job is to find them cold, before any AI sees the file.
# offboard_old.ps1 - runs Fridays 18:00 via Task Scheduler
# author: (unknown) last modified 2019-11-22
Set-ExecutionPolicy Bypass -Force
$admin = "CORP\svc-offboard"
$password = "Sv3rL0g!2019"
$sec = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($admin,$sec)
$leavers = Import-Csv "\\fs01\it\leavers.csv"
foreach ($row in $leavers) {
$u = $row.username
Write-Host "Processing $u"
Disable-ADAccount -Identity $u -Credential $cred
Get-ADUser $u -Properties MemberOf | Select -Expand MemberOf |
ForEach-Object { Remove-ADGroupMember $_ -Members $u `
-Confirm:$false -Credential $cred }
# archive then remove home drive
Copy-Item "\\fs01\home\$u" "\\fs01\archive\$u" -Recurse -Force
Remove-Item "\\fs01\home\$u" -Recurse -Force
# clear old profile
Get-ChildItem "\\fs01\profiles\" | Where-Object {
$_.Name -like "*$u*" } | Remove-Item -Recurse -Force
Set-ADUser $u -Description "Offboarded $(Get-Date)" -Credential $cred
}
Write-Host "Done."
Also create contractors.csv — the input for the new script you will generate:
username,manager,exit_date
c.rakesh,priya.m,2026-08-14
c.anjali,priya.m,2026-08-14
c.dmitri,sunil.v,2026-08-21
,priya.m,2026-08-14
c.wei,sunil.v,2026-08-31
Yes, row four has an empty username. That is deliberate — the CSV is the test of whether your generated script validates input, because offboard_old.ps1 demonstrably does not.
legacy-risk-report.md, each as: line/behavior · what goes wrong · trigger condition. This pre-AI pass matters: your review skill is what you are training, and you need a baseline of what you catch unaided.$u = "" through each line. Write down exactly what Remove-Item "\\fs01\home\$u" -Recurse -Force and the wildcard profile cleanup do when $u is empty. This is the moment the lab exists for: say the blast radius out loud, in writing.offboard_new.ps1.review-checklist.md: (1) -WhatIf genuinely wired through every destructive call, not just declared; (2) least privilege — no Domain Admin assumptions, credential prompted or delegated, never stored; (3) error paths — a failed disable must stop that user's pipeline, not continue to deletion; (4) no hardcoded secrets anywhere, including "example" ones; (5) filters scoped — no -Filter *, no wildcard matches on names; (6) input validation — the empty row must be skipped and logged. AI drafts routinely fail two or three of these on the first pass. Fix each failure yourself or via a targeted re-prompt, and record the before/after.Invoke-ScriptAnalyzer -Path .\offboard_new.ps1 -Severity Warning,Error. Expected output: findings such as PSAvoidUsingPlainTextForPassword or PSUseShouldProcessForStateChangingFunctions if your hardening was incomplete. Iterate until clean, and paste the final clean output into the checklist.-WhatIf only. Expected output: WhatIf lines for the four valid users, one logged skip for the malformed row, and zero actual changes. If the malformed row produced a WhatIf line targeting an empty identity, your validation gate is cosmetic — fix it.legacy-risk-report.md with a recommendation a manager can act on: retire / rewrite / harden, the two dangers named in plain language, and what the Friday job should be replaced with. One paragraph, no jargon.Never let "it has run fine for seven years" stand as a safety argument. offboard_old.ps1 has run fine because its kill condition — one empty cell in a CSV nobody validates — has not happened yet. Safety is a property of the script, not of its luck to date.
A note on how you prompt for the replacement: the requirements list in step 4 is doing real work. An open-ended "write me an offboarding script" reliably produces the same defect classes the legacy script has — no validation, no -WhatIf, optimistic error handling — because the AI reproduces the average script on the internet, and the average script is unsafe. Stating the gates in the prompt gets you perhaps eighty percent of the way; the review protocol exists for the twenty percent the AI claims to have implemented but did not wire through. Prompting well and reviewing anyway is the posture; prompting well instead of reviewing is how the vulnerability studies got their 100% figure.
Keep your step-4 prompt and the six-gate checklist together in your prompt library — the pair is reusable for every destructive script you generate from now on, and the checklist is the interview artifact that proves you review what AI writes.
legacy-risk-report.md contains your pre-AI findings, the AI comparison, and both planted dangers named with trigger conditions.offboard_new.ps1 passes all six review gates, with the checklist showing at least one AI-draft failure you caught and fixed.-WhatIf dry run shows four planned changes, one logged skip, zero executions.Self-grading rubric (pass = 7/10): both planted dangers found before AI assistance (0–2) · empty-row blast radius correctly traced (0–2) · six gates checked with at least one real AI-draft defect caught (0–3) · analyzer clean + honest dry run (0–2) · actionable verdict (0–1).
AI writes the script in thirty seconds; the six-gate review is where the sysadmin earns the title — because every studied AI-generated admin script shipped with exploitable flaws, and the legacy script that "ran fine for years" was one blank cell away from deleting the file server.