T09 · Insecure Skill Coding Practices
- Location
scripts/spawn-agent.sh:96- Finding
Shell Command Injection Through Generated Agent Runner
- Content
View full analysis
"$RUNNER" << RUNEOF #!/usr/bin/env bash set -o pipefail cd "$WORKTREE_DIR" echo "[runner] Starting codex/$MODEL ..." MAX_RETRIES=2 RETRY=0 CUR_MODEL="$MODEL" while true; do codex exec --full-auto -c "model=\$CUR_MODEL" -c "model_reasoning_effort=$REASONING" - < "$PROMPT_FILE" 2>&1 EXIT=\$? if [ "\$EXIT" -eq 0 ]; then echo "[runner] ✅ Agent completed successfully" break fi RETRY=\$((RETRY + 1)) if [ "\$RETRY" -gt "\$MAX_RETRIES" ]; then echo "[runner] ❌ Max retries reached" break fi echo "[runner] 🔄 Retry \$RETRY/\$MAX_RETRIES ..." sleep 10 done RUNEOF chmod +x "$RUNNER" ``` The affected values originate from command-line or batch JSON input: ```bash TASK_ID="${2:?Missing task-id}" MODEL="${5:-}" REASONING="${6:-}" ``` ### Technical Analysis The script dynamically creates an executable shell script using an unquoted heredoc. Values derived from `TASK_ID`, `MODEL`, and `REASONING` are inserted directly into the generated shell source. Shell quoting in the template does not safely serialize these values. An input containing a double quote, newline, command substitution, or other shell syntax can terminate the intended expression and introduce new commands. The resulting file is made executable and subsequently started in tmux. For example, a malicious model or reasoning value containing shell syntax can modify the generated `CUR_MODEL` assignment or `codex exec` command. A task identifier also influences `WORKTREE_DIR`, which is embedded in the generated `cd` statement. ### Attack Path 1. An attacker supplies a crafted `model`, `reasoning`, or task identifier through the tasks JSON or direct script arguments. 2. `scripts/spawn-batch.sh` r ...[truncated 880 chars]- Remediation
View remediation
&2; exit 1 ;; esac ``` - If script generation is unavoidable, serialize every inserted value with `printf '%q'` before writing it into shell source. - Use `--` where supported when passing values to commands. - Run agents with a dedicated, minimally privileged account that does not have unrestricted access to production credentials or protected branches. - Add automated tests containing quotes, newlines, command substitutions, traversal sequences, and leading dashes. ]]>
