T09 · Insecure Skill Coding Practices
- Location
bin/materials-cli.js:19- Finding
Windows Command Injection Through Shell-Enabled CLI Launcher
- Content
View full analysis
{ ``` ### Technical Analysis The launcher appends untrusted command-line arguments directly to the arguments passed to `spawn()`. On Windows, it explicitly enables `shell: true`, causing Node.js to invoke the command through the platform shell rather than executing the Node binary directly. Arguments supplied for prompts, schema paths, output paths, or other CLI options may contain Windows shell metacharacters. When passed through the shell, these characters can be interpreted as command separators or redirection operators instead of remaining literal argument content. This creates a command-injection boundary between CLI input and `cmd.exe`. Although the executable path is fixed to `process.execPath`, that does not eliminate the risk because the untrusted values are included in the shell-parsed command line. ### Attack Path 1. An attacker supplies a crafted CLI argument, schema path, output path, or generation prompt containing Windows shell syntax. 2. A victim invokes `materials` on Windows with the attacker-controlled value. 3. The launcher copies the value from `process.argv.slice(2)` into the spawned argument list. 4. Because `shell` is enabled on Windows, the argument list is converted into a shell command line. 5. The shell interprets embedded metacharacters and executes the injected command. 6. The command runs with the same account and privileges as the user who launched the CLI. ### Impact Assessment Successful exploitation permits arbitrary command execution with the invoking user's privil ...[truncated 374 chars]- Remediation
View remediation
{ console.error(`Failed to launch CLI: ${error.message}`); process.exit(1); }); child.on('exit', (code, signal) => { if (signal) { process.kill(process.pid, signal); } else { process.exit(code ?? 1); } }); ``` Add Windows-specific tests containing spaces, quotes, ampersands, pipes, redirection characters, and command-substitution-like input to verify that all values remain literal arguments. ]]>
