T09 · Insecure Skill Coding Practices
Error
- Location
- index.js:6
- Finding
- Shell Command Injection Through Unsanitized CLI Arguments<![CDATA[ ## Vulnerability Details **File Location**: `index.js:6-11` **Vulnerability Type**: OS command injection **Risk Level**: Critical ### Vulnerable Code ```javascript const args = process.argv.slice(2).join(' '); const scriptDir = path.dirname(__filename); const result = execSync(`"${scriptDir}/scripts/scan.sh" ${args}`, { encoding: 'utf8', stdio: 'inherit' }); console.log(result); ``` ### Technical Analysis The entry point joins all command-line arguments into a single string and interpolates that string into a command executed by `execSync`. Because `execSync` invokes a shell for string commands, shell metacharacters in an argument—such as semicolons, command substitutions, backticks, pipelines, and redirections—are interpreted as shell syntax rather than passed literally to `scan.sh`. The target argument is therefore an arbitrary command-execution channel. No quoting, escaping, validation, or shell-free process invocation protects the boundary between the target value and the command line. ### Attack Path 1. An attacker persuades a user or automation system to invoke the Node.js entry point with a crafted scan target. 2. The crafted value contains shell syntax, such as a command separator or command substitution. 3. `process.argv.slice(2).join(' ')` preserves that shell syntax. 4. The value is inserted directly into the command passed to `execSync`. 5. The operating-system shell interprets the injected syntax and executes the attacker's command. For example, an argument structurally equivalent to `legitimate-target; attacker-command` would cause the second command to be interpreted by the shell. ### Impact Assessment Successful exploitation provides arbitrary command execution with all privileges of the scanner process. Depending on the invoking account, this may permit: - Reading or modifying any files accessible to the user. - Accessing environment variables and local credentials. - Downloading and executing additional payloads. ...[truncated 277 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Use a shell-free child-process API and pass every argument as a separate array element: ```javascript const { execFileSync } = require('child_process'); const path = require('path'); const scriptPath = path.join(__dirname, 'scripts', 'scan.sh'); execFileSync(scriptPath, process.argv.slice(2), { stdio: 'inherit' }); ``` Additional hardening should include: 1. Validate that only documented options and target formats are accepted. 2. Reject control characters and malformed targets before invoking the scanner. 3. Avoid `shell: true` and never build command strings from user-controlled input. 4. Add regression tests using semicolons, backticks, `$()`, pipes, spaces, and redirections. 5. Run the scanner under a minimally privileged account. ]]>
