T09 · Insecure Skill Coding Practices
- Location
slither-integration.js:73- Finding
Shell Command Injection Through the Project Path
- Content
View full analysis
Vulnerability Details
File Location:
slither-integration.js:73-79
Vulnerability Type: OS command injection
Risk Level: Highjavascript // Run Slither with JSON output const cmd = `slither ${projectPath} --json ${outputFile} 2>/dev/null`; execSync(cmd, { stdio: 'pipe', timeout: 300000, // 5 minute timeout cwd: projectPath.includes('/') ? path.dirname(projectPath) : process.cwd() });Technical Analysis
projectPathoriginates from the first command-line argument and is interpolated directly into a command string passed toexecSync. When Node.js receives a string in this form, it executes the command through a system shell.No quoting, escaping, allowlist validation, or shell-metacharacter rejection is applied. An attacker who can control the project path can therefore inject command separators, substitutions, redirections, or other shell syntax. The exception handler does not prevent exploitation because the injected command runs before control returns to JavaScript.
Attack Path
- The attacker gains control over the target path passed to the integration, such as through an automated audit service, CI job parameter, or wrapper application.
- The attacker supplies a shell payload as the path:
bash node slither-integration.js '.; touch PWNED; #' --slither-only - The application constructs a command equivalent to:
bash slither .; touch PWNED; # --json /tmp/slither-....json 2>/dev/null - The shell executes
touch PWNEDindependently of Slither. - The attacker can replace that proof-of-concept command with any command available to the process account.
Using
--slither-onlyavoids the earlierfs.statSync(projectPath)call and sends the malicious value directly torunSlither.Impact Assessment
Successful exploitation provides arbitrary command execution with the operating-system privileges of the Node.js process. An ...[truncated 431 chars]
- Remediation
View remediation
Remediation Suggestions
- Do not construct a shell command from user-controlled input.
- Replace
execSyncwithspawnSyncorexecFileSyncand pass arguments as an array:javascript const { spawnSync } = require('child_process'); const result = spawnSync( 'slither', [resolvedProjectPath, '--json', outputFile], { stdio: 'pipe', timeout: 300000, cwd: fs.statSync(resolvedProjectPath).isDirectory() ? resolvedProjectPath : path.dirname(resolvedProjectPath), shell: false } ); - Canonicalize the target with
fs.realpathSyncand confirm it exists before execution. - If the application restricts audits to a workspace, verify that the canonical path remains inside that workspace.
- Reject unexpected option-like paths or terminate utility options with
--if Slither supports it. - Run analysis under a dedicated, unprivileged account with restricted filesystem and network access.
- Add regression tests using paths containing spaces and shell characters such as
;,$(), backticks, pipes, and redirections.
