T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:178
- Finding
- Shell Command Injection Through Unescaped Prompt and Branch Interpolation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 178-215 **Vulnerability Type**: Shell command injection **Risk Level**: Critical ### Vulnerable Code ```text Task ID: <task or N/A> Project Key: <project key or N/A> Branch Name: <branch_name or N/A> User Objective: <objective> Execution Requirements: 1) Work only inside <cwd>. 2) Complete the requested work. 3) Use branch <branch_name> for commits/pushes when provided. 4) After completion, return a short completion summary. ``` ```bash bash pty:true workdir:<cwd> command:"claude --dangerously-skip-permissions '<rendered_prompt>'" ``` ```bash bash pty:true workdir:<cwd> command:"codex exec --dangerously-bypass-approvals-and-sandbox '<rendered_prompt>'" ``` ```bash bash pty:true workdir:<cwd> command:"GEMINI_SANDBOX=false gemini -p '<rendered_prompt>'" ``` ### Technical Analysis The skill inserts the user-controlled objective and partially user-controlled branch name into `<rendered_prompt>`, then embeds that prompt inside a single-quoted shell argument. It does not specify any escaping or argument-safe process execution. A single quote in the objective can terminate the shell argument. Subsequent text is then interpreted by the shell rather than passed to the coding agent. The same general risk affects other interpolated values, including branch names and paths, where placeholders are inserted into shell command strings without robust quoting. The branch-name checks only reject `..`, a leading slash, and an empty value. They do not constitute shell metacharacter validation and are not a substitute for avoiding shell interpolation. This issue is especially severe because all documented engine invocations disable their respective permission or sandbox controls. ### Attack Path 1. An attacker supplies a PREQSTATION task whose objective contains a quote followed by shell syntax, for example: ```text preq: update documentation'; id > /tmp/preqstation-proof; # ``` 2. The ski ...[truncated 1288 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not construct commands by concatenating user-controlled values into a shell string. 2. Invoke each engine through an argument-vector API, for example by passing the executable and each argument as separate values without `bash -c`. 3. If the platform only supports shell command strings, apply a proven POSIX shell-escaping routine independently to every dynamic argument. Do not implement escaping through simple quote replacement. 4. Pass long prompts through standard input or a securely created prompt file rather than embedding them in command text. 5. Validate branch names with `git check-ref-format --branch` and restrict them to a conservative allowlist such as letters, digits, `/`, `_`, `.`, and `-`. 6. Canonicalize and validate every filesystem path before use. Ensure the resulting worktree remains beneath the configured worktree root. 7. Add regression tests covering single quotes, command substitutions, backticks, semicolons, newlines, redirections, and shell operators in objectives, branch names, project keys, and paths. 8. Restore sandboxing and approval controls so a quoting defect cannot immediately become unrestricted host command execution. ]]>
