T09 · Insecure Skill Coding Practices
- Location
- SKILL.md:101
- Finding
- Shell Command Injection Through Unsafe HTML Interpolation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:101-103` and `SKILL.md:125-128` **Vulnerability Type**: Shell command injection caused by unsafe interpolation into shell-quoted JSON **Risk Level**: High ### Vulnerable Code ```bash curl -X POST https://gui.new/api/canvas \ -H 'Content-Type: application/json' \ -d '{"title": "Star Catcher Game ⭐", "html": "<your html here>"}' ``` ```bash curl -X PUT https://gui.new/api/canvas/abc123xyz \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer tok_...' \ -d '{"html": "<updated html>"}' ``` ### Technical Analysis The skill instructs the agent to insert generated HTML directly into a single-quoted shell argument passed to `curl`. Generated project content can be influenced by the user and can legitimately contain apostrophes, quotation marks, backslashes, newlines, or shell metacharacters. JSON escaping does not provide shell escaping. If inserted HTML contains a single quote, it terminates the shell's quoted `-d` argument. Subsequent shell metacharacters may then be parsed as commands or command separators rather than as HTML data. Even non-malicious apostrophes can corrupt the JSON payload and cause publishing failures. The same unsafe construction is documented for both canvas creation and canvas updates. The update request additionally uses an authorization token in the same shell process, increasing the sensitivity of successful command injection. ### Attack Path 1. An attacker supplies project text or a requested title containing a crafted single quote followed by shell syntax. 2. The agent incorporates that attacker-controlled text into the generated HTML. 3. The generated HTML is substituted for `<your html here>` or `<updated html>` in the documented command. 4. The crafted single quote closes the surrounding shell argument. 5. The shell interprets the remaining metacharacters and text as additional shell operations. 6. Those operations execute with the same opera ...[truncated 1160 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Do not construct shell commands by concatenating generated HTML.** Use a native HTTP client or the approved `gui.new` SDK and pass an in-memory object to a JSON serializer. 2. **Serialize JSON structurally.** For example, create the payload with a JSON library rather than manually embedding HTML inside a JSON string. 3. **If `curl` is unavoidable, generate a payload file safely:** ```bash jq -n \ --arg title "$TITLE" \ --arg html "$HTML" \ '{title: $title, html: $html}' > payload.json curl --fail-with-body \ -X POST 'https://gui.new/api/canvas' \ -H 'Content-Type: application/json' \ --data-binary @payload.json ``` For updates: ```bash jq -n --arg html "$HTML" '{html: $html}' > payload.json curl --fail-with-body \ -X PUT "https://gui.new/api/canvas/$CANVAS_ID" \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $EDIT_TOKEN" \ --data-binary @payload.json ``` 4. **Avoid invoking a command through a shell.** Execute `curl` with an argument array, or use an SDK, so shell metacharacters are never interpreted. 5. **Validate identifiers separately.** Restrict canvas IDs to the documented character set before placing them in a URL. 6. **Protect edit tokens.** Keep tokens in memory where possible, avoid logging them, redact them from errors, and never embed them in generated project files. 7. **Apply defense in depth.** Run the agent as an unprivileged account with filesystem and outbound-network restrictions independently enforced by the runtime. 8. **Add regression tests** using HTML containing apostrophes, quotes, backslashes, newlines, command substitutions, and shell separators. Verify that the content is published literally and that no additional process is executed. ]]>
