T09 · Insecure Skill Coding Practices
- Location
bin/transcribe.js:17- Finding
OS Command Injection Through the Node.js CLI Wrapper
- Content
View full analysis
a.includes('youtube.com') || a.includes('youtu.be')); const lang = args.find(a => ['zh','en','ja','ko','auto'].includes(a)) || 'auto'; if (!url) { console.error('Error: Please provide a YouTube URL'); process.exit(1); } const script = path.join(__dirname, '..', 'transcribe.py'); execSync(`python3 ${script} ${url} ${lang}`, { stdio: 'inherit' }); ``` ### Technical Analysis The CLI wrapper constructs a shell command by directly interpolating `url` into a template string passed to `child_process.execSync`. Unlike argument-oriented process APIs, `execSync` passes the resulting string to a shell. Consequently, shell metacharacters embedded in the URL are interpreted as command syntax. The preceding validation is insufficient because it only verifies that the argument contains the substring `youtube.com` or `youtu.be`. It does not parse the value as a URL, restrict the protocol or hostname, or reject shell metacharacters. Although `lang` is selected from a fixed allowlist, the attacker-controlled `url` is enough to exploit the command. ### Attack Path 1. An attacker supplies a single quoted CLI argument containing a permitted hostname substring followed by shell syntax. For example: ```bash youtube-transcribe "https://youtube.com/watch?v=x; id" ``` 2. The substring check accepts the argument because it contains `youtube.com`. 3. The wrapper creates a command equivalent to: ```bash python3 /path/to/transcribe.py https://youtube.com/watch?v=x; id auto ``` 4. The shell treats the semicolon as a command separator. 5. The injected `id` command executes independently of the transcription process. 6. An attacker can replace `id` with commands that read files, alter system state, download additional ...[truncated 547 chars]- Remediation
View remediation
