Cmd Sanitizer
Prerequisites & Dependencies
- Python 3.10+ (for regex-based linting and rewriting)
- No external runtime dependencies; pure-Python regex patterns
Execution Steps
Input: Provide a raw command string that would be passed to the Windows/PowerShell 5.1 shell.
Pattern detection (applied in order, first match wins):
- A. Bare
&&chaining: Detectcmd1 && cmd2patterns. Rewrite ascmd1; if ($?) { cmd2 }using PowerShell 5.1-compatible;-chaining with$?guard. - B.
$?vs$LASTEXITCODEconfusion: If the string references$?after a native executable invocation, insert$LASTEXITCODEcapture before the$?check and emit a warning. - C. Unquoted paths with spaces: Detect
cmd "path with spaces"orcmd path with spaces(unquoted). Rewrite with double quotes:"cmd path with spaces". - D. UTF-16 pipe risk: If the command pipes output to a file or another command via
|, wrap the pipe target in[System.Text.Encoding]::UTF8.GetString([System.Text.Encoding]::UTF8.GetBytes($input)]to force UTF-8 round-trip, or explicitly set[Console]::OutputEncoding = [System.Text.Encoding]::UTF8. - E. Timeout-kill indeterminacy: If a
timeoutor-Timeoutflag is present, emit a mandatory guard: after the timeout fires, re-run the command without timeout or verify post-execution state, and tag the result asINDETERMINATEuntil manual confirmation.
- A. Bare
Rewriting / guard insertion: After pattern detection, produce a sanitized command string that:
- Replaces bare
&&with; if ($?) { ... } - Quotes any unquoted paths containing spaces
- Prepends
$LASTEXITCODE = & cmdbefore any$?usage - Appends UTF-8 encoding guard for pipe sequences
- Appends
Indeterminate: truemarker if timeout flags are detected, with a required manual re-confirmation step
- Replaces bare
Output: Return a structured object:
{ "original": "<original command string>", "sanitized": "<rewritten command with guards>", "warnings": ["<list of detected patterns>"], "requires_manual_confirm": <boolean> }
Windows PowerShell 5.1 Specific Rules
| Pattern | Detection Regex | Rewrite Rule |
|---|---|---|
Bare && chaining |
/&&(?!\s)/g |
Replace with ; if ($?) { and append } |
$? after exec |
/$?\s*[ | >]/g |
| Unquoted spaced paths | (\b\w+\s+\w+)(?!\s*") (outside already-quoted context) |
Wrap matched path in " |
| UTF-16 pipe risk | `|[^ | ]*(` |
| Timeout kill tag | -Timeout\s+\d+ / timeout\s+\d+ |
Set requires_manual_confirm = true and append Indeterminate: true note |
Example
Input:
python build.py && python test.py
Output:
{
"original": "python build.py && python test.py",
"sanitized": "python build.py; if ($?) { python test.py }",
"warnings": ["Bare && chaining detected - rewritten with $? guard"],
"requires_manual_confirm": false
}
Input:
node scripts/lint.js | out-file results.txt
Output:
{
"original": "node scripts/lint.js | out-file results.txt",
"sanitized": "node scripts/lint.js | out-file results.txt; [Console]::OutputEncoding = [System.Text.Encoding]::UTF8",
"warnings": ["UTF-16 pipe risk detected - UTF-8 encoding guard appended"],
"requires_manual_confirm": false
}
Input:
timeout 30 python heavy-task.py
Output:
{
"original": "timeout 30 python heavy-task.py",
"sanitized": "timeout 30 python heavy-task.py",
"warnings": ["Timeout flag detected - result marked INDETERMINATE until manual re-confirmation"],
"requires_manual_confirm": true
}