T09 · Insecure Skill Coding Practices
- Location
scripts/viral-search.js:76- Finding
Shell Command Injection in X/Twitter Search
- Content
View full analysis
Vulnerability Details
File Location:
scripts/viral-search.js, lines 76-80
Vulnerability Type: OS command injection
Risk Level: CriticalVulnerable 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
- An attacker supplies or persuades the Agent to search for a crafted topic containing shell command substitution, such as
topic $(attacker_command). - The value is appended to
searchQuery. - The script only escapes double quotation marks.
execSyncpasses the constructed string to a shell.- The shell evaluates the command substitution before invoking
bird. - 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.
- An attacker supplies or persuades the Agent to search for a crafted topic containing shell command substitution, such as
- Remediation
View remediation
Remediation Suggestions
Replace shell-based
execSyncwith 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.
