T09 · Insecure Skill Coding Practices
- Location
build.sh:11- Finding
PowerShell Command Injection Through Unvalidated Version Input
- Content
View full analysis
Building $ZIP_NAME (ver=$VER)" ``` ```bash elif command -v powershell.exe >/dev/null 2>&1 || command -v powershell >/dev/null 2>&1; then PSH="$(command -v powershell.exe 2>/dev/null || command -v powershell)" WIN_SRC="$(cygpath -w "$(pwd)/$(basename "$STAGE_DIR")" 2>/dev/null || echo "$(pwd)/$(basename "$STAGE_DIR")")" WIN_OUT="$(cygpath -w "$OUT_DIR/$ZIP_NAME" 2>/dev/null || echo "$OUT_DIR/$ZIP_NAME")" "$PSH" -NoProfile -Command "Compress-Archive -Path '${WIN_SRC}' -DestinationPath '${WIN_OUT}' -Force" ``` ### Technical Analysis The first positional argument is accepted as `VER` without format validation. This attacker-controlled value is incorporated into `OUT_DIR`, `ZIP_NAME`, and ultimately `WIN_OUT`. The PowerShell fallback embeds `WIN_OUT` directly into source code passed through PowerShell's `-Command` option: ```powershell Compress-Archive -Path '${WIN_SRC}' -DestinationPath '${WIN_OUT}' -Force ``` Although the paths are enclosed in PowerShell single quotes, a single quote contained in `VER` can terminate the string literal. The remainder of the value can then introduce additional PowerShell statements. Shell quoting at the Bash layer does not prevent this because the vulnerable interpretation occurs later when PowerShell parses the constructed command string. The absence of validation also permits path separators and traversal components in `VER`, potentially moving output files outside the intend ...[truncated 1602 chars]- Remediation
View remediation
&2 exit 1 fi ``` 2. For a strict release process, allow only semantic versions: ```bash if [[ ! "$VER" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "ERROR: version must use X.Y.Z format" >&2 exit 1 fi ``` 3. Explicitly reject path and command metacharacters, including quotes, slashes, backslashes, semicolons, whitespace, dollar signs, backticks, and traversal sequences. 4. Do not interpolate paths into PowerShell program text. Pass them as encoded or positional arguments to a fixed script block. For example, invoke a checked PowerShell script file whose parameters are bound by PowerShell rather than concatenated into `-Command`. 5. Resolve and verify the final output path before creating directories or archives. Confirm that it remains under the intended parent directory. 6. Add regression tests using versions containing single quotes, semicolons, whitespace, path separators, and `..`, and assert that every such value is rejected. ]]>
