T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/estimate.mjs:15
- Finding
- Shell Command Injection Through Auction ID and Proxy Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/estimate.mjs:8, 15-18, 25, 177` **Vulnerability Type**: OS command injection **Risk Level**: High ### Vulnerable Code ```js const PROXY = process.env.PROXY_SOCKS5 || 'socks5://127.0.0.1:1080'; // 辅助函数:执行curl命令 function curl(url) { try { return execSync( `curl -s --proxy ${PROXY} -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)" "${url}" 2>/dev/null`, { encoding: 'utf8', timeout: 30000 } ); } catch (e) { return ''; } } ``` The URL passed to this function contains a command-line argument: ```js async function getProductInfo(id) { const url = `https://auctions.yahoo.co.jp/jp/auction/${id}`; const html = curl(url); ``` The product IDs originate directly from process arguments: ```js async function main() { const ids = process.argv.slice(2); ``` ### Technical Analysis The application builds a shell command by interpolating two untrusted values into a template string passed to `execSync()`: 1. `PROXY` is populated from the `PROXY_SOCKS5` environment variable and is inserted into the command without shell quoting. 2. `id` originates from a command-line argument and is incorporated into `url`. Although the URL is enclosed in double quotes, shell command substitution and certain other shell expansions remain active inside double-quoted strings. Because `execSync()` executes the resulting string through a shell, shell metacharacters in either value can change the intended command structure. The application does not validate auction IDs or parse and constrain the proxy URL before command construction. The 30-second timeout limits execution duration but does not prevent an injected command from running or spawning an independent process. ### Attack Path 1. An attacker obtains the ability to influence an auction ID supplied to the Skill, or the `PROXY_SOCKS5` environment variable. 2. The attacker supplies a value containing shell syntax, such as command ...[truncated 1118 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not invoke `curl` through a shell. Use `execFileSync()` or `spawnSync()` with a separate argument array: ```js import { execFileSync } from 'child_process'; function curl(url) { try { return execFileSync( 'curl', [ '-s', '--proxy', PROXY, '-H', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)', url ], { encoding: 'utf8', timeout: 30000, shell: false } ); } catch { return ''; } } ``` 2. Prefer a native Node.js HTTP client with explicit proxy support, removing the command-execution boundary entirely. 3. Validate each auction ID before constructing the URL. If Yahoo Auction IDs are expected to contain one letter followed by digits, enforce a strict allowlist such as: ```js if (!/^[a-z][0-9]+$/i.test(id)) { throw new Error('Invalid auction ID'); } ``` 4. Parse `PROXY_SOCKS5` with the `URL` class. Permit only required schemes such as `socks5:` and reject malformed values, unexpected protocols, control characters, and unsupported components. 5. Run the Skill with a minimally privileged account, a restricted environment, and only the filesystem and network access needed for auction estimation. 6. Add security tests covering shell metacharacters, command substitution syntax, whitespace, quotes, and malformed proxy URLs. ]]>
