T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/viral-search.js:76
- Finding
- Shell Command Injection in X/Twitter Search## Vulnerability Details **File Location**: `scripts/viral-search.js`, lines 76-80 **Vulnerability Type**: OS command injection **Risk Level**: Critical ### Vulnerable Code ```javascript const fetchCount = Math.min(limit * 3, 40); const raw = execSync(`bird search "${searchQuery.replace(/"/g, '\\"')}" -n ${fetchCount} --json`, { encoding: 'utf8', timeout: 30000, stdio: ['pipe', 'pipe', 'pipe'], }); ``` ### Technical Analysis The user-controlled search query is interpolated into a command string passed to `execSync`, which executes the string through a system shell. Replacing double quotation marks with `\"` is not sufficient shell escaping. In particular, command substitutions such as `$(command)` and backtick expressions remain active inside double-quoted shell strings. Consequently, an attacker who can influence the search topic can cause the shell to execute an arbitrary local command rather than treating the entire value as a literal search query. ### Attack Path 1. An attacker supplies or persuades the Agent to search for a crafted topic containing shell command substitution, such as `topic $(attacker_command)`. 2. The value is appended to `searchQuery`. 3. The script only escapes double quotation marks. 4. `execSync` passes the constructed string to a shell. 5. The shell evaluates the command substitution before invoking `bird`. 6. The injected command runs with the same operating-system privileges and environment as the Agent. ### Impact Assessment Successful exploitation permits arbitrary command execution under the account running the Skill. An attacker could read or modify accessible files, retrieve environment variables and API credentials, access browser or social-media authentication state, invoke network utilities, alter generated content, or use the Agent's account to compromise other reachable resources.
- Remediation
- ## Remediation Suggestions Replace shell-based `execSync` with an argument-array API that does not invoke a shell: ```javascript const { execFileSync } = require('child_process'); const raw = execFileSync( 'bird', ['search', searchQuery, '-n', String(fetchCount), '--json'], { encoding: 'utf8', timeout: 30000, stdio: ['pipe', 'pipe', 'pipe'], shell: false, } ); ``` Also validate query length and reject control characters. Do not attempt to solve this issue using ad hoc shell escaping; keeping untrusted values out of shell command strings is the safer design.
