T09 · Insecure Skill Coding Practices
Error
- Location
- tool.js:26
- Finding
- Arbitrary Command Execution Through Shell Command Injection<![CDATA[ ## Vulnerability Details **File Location**: `tool.js:26-44` **Vulnerability Type**: Shell command injection **Risk Level**: Critical ### Vulnerable Code ```js try { // 构建命令 const scriptPath = path.join(__dirname, 'index.js'); const args = [ 'node', scriptPath, '--url', url, '--language', language, '--format', output_format ]; // 执行转写 const output = execSync(args.join(' '), { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, // 10MB timeout: 300000 // 5分钟超时 }); ``` ### Technical Analysis The `url`, `language`, and `output_format` values originate from tool parameters. They are placed into an argument array, joined into a single string, and passed to `execSync`. When `execSync` receives a string, Node.js executes it through a system shell. Because the parameter values are neither escaped nor validated, shell metacharacters such as command separators, substitutions, pipes, and redirections are interpreted by the shell instead of being passed exclusively to `index.js`. The metadata restricts `output_format` through an enum, but runtime enforcement is not performed by this function. More importantly, `url` and `language` remain directly injectable. ### Attack Path 1. An attacker or untrusted user invokes `video_to_text`. 2. The attacker supplies a tool parameter containing shell syntax, such as a URL followed by a shell command separator and an attacker-selected command. 3. `video_to_text` adds the malicious value to `args`. 4. `args.join(' ')` constructs a shell command string containing the injected syntax. 5. `execSync` invokes the system shell. 6. The shell interprets and executes the injected command with the permissions of the Agent process. No successful media download or transcription is required for exploitation because the injected command is interpreted before `index.js` validates or processes the URL. ### Impact Assessment Successful exploitation provides arbitrary operating-system comm ...[truncated 603 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Replace shell-string execution with an API that passes arguments directly and does not invoke a shell: ```js const { execFileSync } = require('child_process'); const output = execFileSync( process.execPath, [scriptPath, '--url', url, '--language', language, '--format', output_format], { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: 300000, shell: false } ); ``` - Alternatively, use `spawn` or `spawnSync` with an argument array and `shell: false`. - Validate `language` against an explicit allowlist such as `zh`, `en`, and `ja`. - Validate `output_format` at runtime against `text` and `srt`; do not rely solely on metadata validation. - Parse `url` with the standard `URL` class and reject malformed values. - Do not attempt to mitigate this issue only by manually quoting values. Eliminating the shell is the reliable fix. - Run the Skill under a restricted service account with minimal filesystem, network, and credential access as defense in depth. ]]>
