T09 · Insecure Skill Coding Practices
- Location
scripts/batch_screen.js:43- Finding
Shell Command Injection in Batch Resume Processing
- Content
View full analysis
Vulnerability Details
File Location:
scripts/batch_screen.js:43-49
Vulnerability Type: OS command injection through shell-based command construction
Risk Level: HighVulnerable Code
js if (file.toLowerCase().endsWith('.pdf')) { const tempTxt = path.join('/tmp', file + '.txt'); execSync('pdftotext "' + filePath + '" "' + tempTxt + '"'); processPath = tempTxt; isTemp = true; } const output = execSync('node ' + path.join(__dirname, 'screen_resume.js') + ' "' + processPath + '" --lang "' + lang + '" --yoe "' + yoe + '"', { encoding: 'utf8' });Technical Analysis
The script constructs shell commands by concatenating untrusted values into strings passed to
child_process.execSync. The affected values include:- Resume filenames obtained from the user-selected directory.
- The
--langcommand-line argument. - The
--yoecommand-line argument. - Paths derived from these inputs.
Wrapping values in double quotes does not make shell construction safe. Command substitutions such as
$(command)remain active inside double quotes, and embedded quotes can terminate an argument and introduce additional shell syntax.Because
execSyncinvokes a shell, these values can alter the intended command rather than being treated exclusively as arguments.Attack Path
- An attacker supplies a crafted option such as a
--langvalue containing shell substitution, or places a PDF with a shell-bearing filename in the scanned directory. batch_screen.jsreads the value without validation or escaping.- The value is concatenated into the
pdftotextornodecommand string. execSyncpasses the constructed string to the operating-system shell.- The shell evaluates the injected syntax and executes the attacker's command.
Impact Assessment
Successful exploitation permits arbitrary command execution with the same operating-system privileges as the Node.js process. ...[truncated 320 chars]
- Remediation
View remediation
Remediation Suggestions
-
Replace
execSyncwithexecFileSyncorspawnSyncand pass arguments as an array without enabling a shell. -
Invoke PDF conversion as follows:
js execFileSync('pdftotext', [filePath, tempTxt], { shell: false, stdio: 'pipe' }); -
Invoke the Node.js script using
process.execPathand an argument array:js execFileSync(process.execPath, [ path.join(__dirname, 'screen_resume.js'), processPath, '--lang', lang, '--yoe', yoe ], { encoding: 'utf8', shell: false }); -
Validate
langandyoeagainst explicit formats, lengths, and accepted values. -
Reject filenames containing control characters and enforce file-type validation based on content rather than extension alone.
-
Run document conversion in a sandboxed, low-privilege process with resource limits.
-
