T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:60
- Finding
- Command Injection Through Unsafe Shell Template Substitution## Vulnerability Details **File Location**: `SKILL.md`, lines 60-94 **Vulnerability Type**: Shell command injection through user-controlled template values **Risk Level**: High ### Vulnerable Code ```bash curl -X POST http://localhost:8080/api/v1/tasks/execute \ -H "Content-Type: application/json" \ -d '{ "scriptId": "bilibili-search", "params": { "keyword": "{{keyword}}", "sort": "click" // click, pubdate, dm } }' ``` ```bash curl -X POST http://localhost:8080/api/v1/tasks/execute \ -H "Content-Type: application/json" \ -d '{ "scriptId": "bilibili-subtitle", "params": { "videoUrl": "{{videoUrl}}" } }' ``` ```bash curl -X POST http://localhost:8080/api/v1/tasks/execute \ -H "Content-Type: application/json" \ -d '{ "scriptId": "bilibili-info", "params": { "videoUrl": "{{videoUrl}}" } }' ``` ### Technical Analysis The documented commands place the JSON request body inside a single-quoted shell argument while embedding the user-controlled template values `{{keyword}}` and `{{videoUrl}}`. No input validation, shell escaping, JSON serialization, or URL allowlisting is specified. If an agent implements these examples through direct textual substitution and invokes them with the declared `exec` capability, an input containing a single quote can terminate the quoted `-d` argument. Shell operators and additional commands following that quote would then be interpreted by the shell rather than treated as JSON data. This violates the separation between data and executable command syntax. JSON escaping alone would not address the problem if the resulting value is still interpolated into a shell command string; the command must instead be constructed without shell parsing. The search example also contains a `//` comment, which is not valid JSON. Although this is not independently a security vulnerability, it ca ...[truncated 1488 chars]
- Remediation
- ## Remediation Suggestions 1. Do not substitute user input into a shell command string. Invoke `curl` through an argument-array API that bypasses shell parsing. 2. Construct the request body with a proper JSON serializer. Pass the resulting JSON as one argument to `curl`, rather than embedding it in quoted shell source. 3. If shell execution is unavoidable, pass values through environment variables and use a JSON-aware utility such as `jq`: ```bash payload="$(jq -n --arg keyword "$KEYWORD" \ '{scriptId: "bilibili-search", params: {keyword: $keyword, sort: "click"}}')" curl --fail-with-body \ -X POST "${BROWSERWING_URL}/api/v1/tasks/execute" \ -H "Content-Type: application/json" \ --data-binary "$payload" ``` The environment variable assignment itself must also be performed through a structured process API rather than generated shell text. 4. Validate video URLs with a URL parser and allow only HTTPS URLs whose normalized hostname is an approved Bilibili domain. Reject embedded credentials, unexpected schemes, malformed hosts, and control characters. 5. Apply reasonable length and character constraints to search keywords while treating validation as defense in depth, not as a replacement for safe process invocation. 6. Prefer a constrained HTTP client tool scoped to the configured local BrowserWing endpoint instead of granting general-purpose `exec` access. 7. Use `BROWSERWING_URL` consistently and validate its scheme and destination before requests are made. 8. Remove the `// click, pubdate, dm` comment from the JSON example because JSON does not support comments. 9. Add tests using values containing single quotes, quotation marks, newlines, shell operators, command substitutions, and malformed URLs to verify that all inputs remain inert data.
