T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:36
- Finding
- Shell Command Injection Through Untrusted Search Queries and Result IDs<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 36-65 **Vulnerability Type**: Shell command injection through unsafe interpolation of user-controlled and externally sourced values **Risk Level**: High ### Vulnerable Code ```markdown Execute each query: ```bash node tools/clis/exa.js search --query "[ICP-targeted query]" --num-results 20 --text ``` For domain-specific searches, filter to relevant sites: ```bash node tools/clis/exa.js search --query "[query]" --num-results 20 --include-domains "crunchbase.com,linkedin.com" --text ``` To find companies similar to existing customers: ```bash node tools/clis/exa.js search --query "[existing customer name] competitors alternatives" --num-results 15 --text ``` To preview without making API calls: ```bash node tools/clis/exa.js search --query "[query]" --num-results 20 --dry-run ``` ### Step 3: Enrich Top Prospects For the most promising results, fetch detailed content: ```bash node tools/clis/exa.js contents --ids "[id1],[id2],[id3]" --text --highlights ``` ``` ### Technical Analysis The skill instructs the agent to interpolate ideal-customer-profile terms, search queries, customer names, and search-result identifiers directly into shell command templates. These values can originate from users or externally controlled search results. Enclosing a value in double quotes does not make it safe for shell evaluation. Command substitutions such as `$(...)` and backtick expressions are still evaluated inside double-quoted strings. An embedded double quote can also terminate the intended argument and introduce shell operators or additional commands. For example, if an untrusted query contains `$(touch /tmp/exa-skill-poc)`, directly substituting it into the documented template and executing the result through a shell would run the substituted command before or while launching the Node.js CLI. Similar injection may occur through a malicious customer name or externally influenced result ID. ...[truncated 1737 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not construct shell command strings by replacing placeholders with untrusted values. 2. Invoke Node.js and the Exa CLI through a process API that accepts a structured argument array, for example: ```javascript spawn("node", [ "tools/clis/exa.js", "search", "--query", userQuery, "--num-results", "20", "--text" ], { shell: false }); ``` 3. Explicitly require `shell: false` or the equivalent behavior in the execution environment. 4. Validate result IDs with a strict allowlist matching the identifier format expected by the Exa API. Reject unexpected whitespace, quotes, control characters, and shell metacharacters. 5. Apply reasonable length limits and type validation to queries, customer names, domains, and IDs. 6. If a shell is unavoidable, use a well-tested platform-specific argument-escaping library rather than manual quoting. Escaping should be a secondary control, not the primary design. 7. Update the skill documentation to state that placeholders must be passed as literal process arguments and must never be interpolated into a shell command. 8. Add tests using values containing quotes, backticks, `$()`, semicolons, newlines, and shell operators to verify that they remain literal arguments and cannot trigger command execution. ]]>
