T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/voice-processor.js:34
- Finding
- Shell Command Injection Through Unsafe Audio Path Interpolation## Vulnerability Details **File Location**: `scripts/voice-processor.js`, lines 34-42 **Vulnerability Type**: OS command injection **Risk Level**: High **Vulnerable code:** ```javascript async function transcribeVoiceNote(audioFilePath) { try { const scriptDir = path.dirname(__filename); const transcribeScript = path.join(scriptDir, 'transcribe.py'); const { stdout, stderr } = require('child_process').execSync( `python "${transcribeScript}" "${audioFilePath}"`, { maxBuffer: 10 * 1024 * 1024, encoding: 'utf8' } ); ``` ### Technical Analysis `audioFilePath` is interpolated directly into a command string passed to `execSync`. By default, `execSync` processes a string through a system shell. Quoting the path does not make it safe because a path containing a double quote followed by shell metacharacters can terminate the quoted argument and append another command. The vulnerable `transcribeVoiceNote` function is exported as part of the public module API and is documented as accepting a caller-provided file path. Therefore, any integration that passes an untrusted or insufficiently validated path to this function creates a command-execution primitive. The code also incorrectly destructures the return value of `execSync`: with `encoding: 'utf8'`, the method returns a string rather than an object containing `stdout` and `stderr`. This causes normal transcription to fail when `stdout.match` is subsequently called. It does not prevent the injected shell command from running, because command execution occurs before the return value is processed. ### Attack Path 1. An attacker reaches an integration that exposes `transcribeVoiceNote` or otherwise controls the supplied audio path. 2. The attacker submits a path containing a closing quote and shell syntax, such as a path conceptually structured as `" ; attacker-command ; "`. 3. The application embeds that value into the command string with ...[truncated 743 chars]
- Remediation
- ## Remediation Suggestions Replace shell-based execution with `execFile` or `spawn` and pass arguments as an array with shell processing disabled: ```javascript const { execFile } = require('child_process'); const { promisify } = require('util'); const execFileAsync = promisify(execFile); async function transcribeVoiceNote(audioFilePath) { const scriptDir = path.dirname(__filename); const transcribeScript = path.join(scriptDir, 'transcribe.py'); const { stdout } = await execFileAsync( 'python3', [transcribeScript, audioFilePath], { shell: false, maxBuffer: 10 * 1024 * 1024, encoding: 'utf8' } ); // Parse stdout here. } ``` Additionally: - Resolve and validate the path before use. - Restrict accepted paths to an explicitly permitted directory where appropriate. - Reject unexpected file types and non-regular files. - Run the process under a dedicated, least-privileged account. - Add regression tests using paths containing quotes, spaces, command separators, and substitution syntax.
