#30: call python3 with execFileSync to block shell injection in path#34
#30: call python3 with execFileSync to block shell injection in path#34kreinba wants to merge 1 commit into
Conversation
…in path
Replace the /bin/bash -c execSync invocation in src/aibolit.ts with execFileSync('python3', [...args, path]) so the path argument is passed as a single argv element and shell metacharacters in user-supplied paths can no longer execute. The catch branch keeps the previous tolerance of a non-zero exit by parsing whatever stdout the failing call already produced. Tests mock execFileSync alongside execSync, add a regression case asserting the argv shape, and cover both arms of the catch fallback.
📝 WalkthroughWalkthroughThe PR fixes a shell injection vulnerability by replacing shell-based ChangesShell injection fix via execFileSync
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/aibolit.ts (1)
4-4: 💤 Low valueConsider using
execFileSyncforcheck_version()too.For consistency with the security fix,
check_version()could also avoid the shell wrapper. The current code is safe since there's no user input, but usingexecFileSyncthroughout would make the shell-avoidance pattern explicit.♻️ Suggested refactor
-import { execFileSync, execSync } from 'child_process'; +import { execFileSync } from 'child_process';function check_version(): void { - const stdout = execSync(`/bin/bash -c "python3 -m aibolit --version"`).toString(); + const stdout = execFileSync('python3', ['-m', 'aibolit', '--version']).toString(); const match = stdout.match(/^[^ ]+ (\d+\.\d+\.\d+)\n$/);Also applies to: 10-10
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/aibolit.ts` at line 4, Replace the execSync call in check_version() with execFileSync to avoid using a shell: call execFileSync(binary, argsArray, { encoding: 'utf8' }) instead of execSync(commandString); construct argsArray (e.g., ['--version'] or whatever flags were in the string), remove any shell:true usage, and preserve existing stdout parsing and error handling so check_version() returns the same version string on success and throws/handles errors the same way.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/aibolit.ts`:
- Line 4: Replace the execSync call in check_version() with execFileSync to
avoid using a shell: call execFileSync(binary, argsArray, { encoding: 'utf8' })
instead of execSync(commandString); construct argsArray (e.g., ['--version'] or
whatever flags were in the string), remove any shell:true usage, and preserve
existing stdout parsing and error handling so check_version() returns the same
version string on success and throws/handles errors the same way.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e2c3837e-9c19-43f4-97c2-2224b13db124
📒 Files selected for processing (2)
src/aibolit.tstest/aibolit.test.ts
The MCP
find_the_most_critical_design_issuetool passes the user-suppliedpathstraight into/bin/bash -c "...${path}..."viaexecSyncinsrc/aibolit.ts, so any value containing shell metacharacters is parsed by the shell instead of being treated as a filename. A crafted path such asfoo.java; touch /tmp/pwnedruns both halves on the host.The shell wrapper is now gone. The call uses
execFileSync('python3', ['-m', 'aibolit', 'check', '--full', '--filenames', path])so Node handspathtopython3as a single argv element and the shell is never involved. The previous|| truetolerance is preserved by catching the non-zero-exit error and reading whatever stdout the failing call already produced.Ran
make test(28 tests pass, branch coverage stays at 100%),make lint,npx tsc --target es2020 --module nodenext, andnpx . --version/npx . --helplocally. A new regression test assertsexecFileSyncis called with the exact argv shape so a path with;cannot reach a shell again.Fixes #30
Summary by CodeRabbit