T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:156
- Finding
- Shell Command Injection Through Transcript-Derived Webhook Data<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 156-169 **Vulnerability Type**: Unsafe shell interpolation and JSON construction **Risk Level**: High ### Vulnerable Code ```markdown - **webhook**: POST to `dispatch.url` with JSON body: ```json { "agent": "<name>", "task": "<task summary>", "source_quote": "<exact quote>", "log_id": "<log ID>", "timestamp": "<ISO timestamp>" } ``` ```bash curl -s -X POST -H "Content-Type: application/json" \ -d '{"agent":"NAME","task":"TASK","source_quote":"QUOTE","log_id":"ID","timestamp":"TS"}' \ "DISPATCH_URL" ``` ``` ### Technical Analysis The documented command inserts transcript-derived values such as `TASK` and `QUOTE` into a single-quoted shell argument without defining any shell-safe or JSON-safe encoding procedure. These values originate from lifelog transcripts and must therefore be treated as untrusted input. A transcript containing a single quote can terminate the `-d` argument. If the generated value also contains shell syntax, the remaining text may be interpreted as a command when an agent materializes and executes this template. Even where command execution is not achieved, quotes, backslashes, control characters, and newlines can corrupt the JSON document or modify its structure. User approval of a dispatch does not neutralize this vulnerability because the user is not instructed to inspect the generated shell command or recognize shell metacharacters in transcript content. ### Attack Path 1. An attacker speaks near the pendant or otherwise causes a crafted phrase to appear in a lifelog transcript. 2. The phrase addresses a configured agent and resembles an actionable directive, causing it to be extracted as an action item. 3. The Skill places the transcript-derived task and exact quote into the webhook dispatch template. 4. The user approves the apparently legitimate task dispatch. 5. The agent substitutes the untrusted values into the do ...[truncated 768 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Do not construct shell commands by interpolating transcript content. - Generate JSON with a structured encoder, for example: ```bash payload="$(jq -n \ --arg agent "$agent" \ --arg task "$task" \ --arg source_quote "$source_quote" \ --arg log_id "$log_id" \ --arg timestamp "$timestamp" \ '{agent:$agent, task:$task, source_quote:$source_quote, log_id:$log_id, timestamp:$timestamp}')" curl --fail-with-body --silent --show-error \ -H "Content-Type: application/json" \ --data-binary "$payload" \ "$dispatch_url" ``` - Prefer a non-shell HTTP client using a native JSON serializer. - Pass data as arguments or environment values rather than generating executable shell source. - Validate destination URLs and allow only approved `https` hosts. - Display the exact destination and encoded payload before requesting final user approval. - Add tests covering single quotes, double quotes, backslashes, newlines, command substitutions, and shell metacharacters. ]]>
