T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:23
- Finding
- Shell Command Injection Through Unsanitized User-Supplied URL## Vulnerability Details **File Location**: `SKILL.md`, lines 23–29 **Vulnerability Type**: Shell command injection **Risk Level**: High The skill directs the agent to replace `{url}` with an untrusted URL and execute the resulting shell command: ```bash ### Step 2 — 發送請求與解析 (Fetch & Parse) 執行以下 `curl` 指令(請將 `{url}` 替換為實際連結): ```bash curl -X POST [https://api.cobalt.tools/api/json](https://api.cobalt.tools/api/json) \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{"url": "{url}"}' ``` ### Technical Analysis The `{url}` placeholder represents user-controlled input and is embedded directly inside a single-quoted shell argument. Shell quoting does not safely contain an input that can itself include a single quote. A malicious value can terminate the JSON argument and introduce shell separators and additional commands. This vulnerability arises before the request reaches Cobalt: the local shell interprets the constructed command. JSON formatting and `Content-Type` headers therefore provide no protection against shell metacharacters. The endpoint is additionally represented using Markdown-link syntax: ```bash [https://api.cobalt.tools/api/json](https://api.cobalt.tools/api/json) ``` This is not a valid literal URL argument for `curl` and may cause the documented command to fail. Although this is primarily a correctness issue, it reinforces the need to avoid generating executable shell commands from prose through textual substitution. ### Attack Path 1. An attacker supplies an apparent Instagram URL containing a single quote followed by shell control operators and an additional command. 2. The agent follows the skill instruction and replaces `{url}` verbatim with the attacker-controlled value. 3. The single quote in the value closes the `-d` argument prematurely. 4. The shell interprets the remaining input as shell syntax rather than URL data. 5. The inject ...[truncated 1300 chars]
- Remediation
- ## Remediation Suggestions 1. **Do not construct shell commands through placeholder substitution.** Use an HTTP client API that accepts the endpoint, headers, and JSON body as distinct structured values without invoking a shell. 2. **Parse and validate the submitted URL.** Require: - The `https` scheme. - An explicitly allowlisted Instagram hostname, such as `instagram.com` or `www.instagram.com`. - Rejection of embedded credentials, control characters, and malformed URLs. - A path matching the supported Instagram content types. 3. **Serialize the request body with a JSON library.** Do not manually concatenate the URL into JSON, because characters such as quotes, backslashes, and control characters require JSON escaping. 4. **If command-line `curl` is unavoidable, pass arguments without a shell.** Invoke it through an argument-array API and provide each argument separately. Generate the body using a JSON serializer. Do not use `sh -c`, `bash -c`, `eval`, or an equivalent command interpreter. 5. **Correct the endpoint representation.** Use the literal endpoint rather than Markdown-link syntax: ```text https://api.cobalt.tools/api/json ``` 6. **Apply least privilege and execution controls.** Run the downloader in a restricted environment with limited filesystem access, no unnecessary credentials, constrained outbound networking, and a dedicated download directory. 7. **Add negative security tests.** Test URLs containing single quotes, double quotes, backslashes, newlines, shell separators, command substitutions, and malformed hostnames, and verify that none are interpreted as executable syntax.
