T09 · Insecure Skill Coding Practices
- Location
SKILL.md:129- Finding
Unsafe Shell and JSON Interpolation of Untrusted Reply Content
- Content
View full analysis
//issues//comments -f body='' ``` ```bash TOKEN=$(gh auth token) curl --http1.1 -sS -X POST \ -H "Authorization: token $TOKEN" \ -H "Accept: application/vnd.github+json" \ -d '{"body":""}' \ https://api.github.com/repos///issues//comments ``` ### Technical Analysis The documented publication commands interpolate the generated `` directly into shell-quoted arguments and manually constructed JSON. The reply is derived from GitHub issue titles, bodies, and comments, which are attacker-controlled inputs. In the `gh api` command, an apostrophe in the reply can terminate the single-quoted shell argument. If the agent implements the example through textual substitution and passes the result to a shell, subsequent attacker-controlled characters may be interpreted as shell syntax. In the `curl` fallback, the reply is inserted into a manually assembled JSON string without JSON encoding. Double quotes, backslashes, control characters, or newlines can invalidate or alter the request body. Shell quoting can also be disrupted depending on how placeholders are substituted. The Skill includes an explicit publication confirmation gate, which reduces exposure but does not eliminate the vulnerability: approval authorizes publication of the visible reply, not execution of shell syntax embedded in it. ### Attack Path 1. An attacker creates or comments on an Apollo GitHub issue using text containing crafted quotation marks and shell metacharacters. 2. The Skill reads that untrusted issue content and incorporates some of it into the proposed maintainer reply. 3. A maintainer reviews the rendered reply and explicitly approves publication. 4. The agent replaces `` in one of th ...[truncated 1149 chars]- Remediation
View remediation
"$payload_file" gh api "repos/$owner/$repo/issues/$issue_id/comments" \ --method POST \ --input "$payload_file" ``` 3. If `curl` is required, pass only serializer-produced JSON: ```bash payload=$(jq -n --arg body "$reply" '{body: $body}') curl --http1.1 -sS -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/vnd.github+json" \ -H "Content-Type: application/json" \ --data-binary "$payload" \ "https://api.github.com/repos/$owner/$repo/issues/$issue_id/comments" ``` 4. Validate repository coordinates before use: - Owner and repository names must match an allowlisted GitHub identifier pattern. - The issue ID must contain digits only. - Prefer restricting publication to the repository supplied through trusted configuration. 5. Treat issue titles, bodies, comments, and generated replies explicitly as untrusted data. Never evaluate them as commands, templates, or instructions. 6. Keep the existing explicit publication gate, and additionally show the final repository, issue number, and exact rendered comment before execution. 7. Avoid exposing the token as an ordinary shell variable when possible. Prefer authenticated `gh api` execution so token handling remains within the GitHub CLI. ]]>
