-
Notifications
You must be signed in to change notification settings - Fork 0
🔒 Fix command injection vulnerability in command_exists #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5151,7 +5151,9 @@ fn detect_powershell_shell() -> std::io::Result<&'static str> { | |||||||||||||||||
| fn command_exists(command: &str) -> bool { | ||||||||||||||||||
| std::process::Command::new("sh") | ||||||||||||||||||
| .arg("-c") | ||||||||||||||||||
| .arg(format!("command -v {command} >/dev/null 2>&1")) | ||||||||||||||||||
| .arg("command -v \"$1\" >/dev/null 2>&1") | ||||||||||||||||||
| .arg("--") | ||||||||||||||||||
| .arg(command) | ||||||||||||||||||
| .status() | ||||||||||||||||||
|
Comment on lines
5151
to
5157
|
||||||||||||||||||
| .map(|status| status.success()) | ||||||||||||||||||
| .unwrap_or(false) | ||||||||||||||||||
|
|
@@ -5351,6 +5353,24 @@ pub mod pdf_extract; | |||||||||||||||||
|
|
||||||||||||||||||
| #[cfg(test)] | ||||||||||||||||||
| mod tests { | ||||||||||||||||||
|
|
||||||||||||||||||
| #[test] | ||||||||||||||||||
| fn test_command_exists_valid() { | ||||||||||||||||||
| assert!(super::command_exists("ls") || super::command_exists("dir")); | ||||||||||||||||||
| } | ||||||||||||||||||
|
Comment on lines
+5357
to
+5360
|
||||||||||||||||||
|
|
||||||||||||||||||
| #[test] | ||||||||||||||||||
| fn test_command_exists_invalid() { | ||||||||||||||||||
| assert!(!super::command_exists( | ||||||||||||||||||
| "nonexistentcommandthatshouldneverexist123" | ||||||||||||||||||
| )); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| #[test] | ||||||||||||||||||
| fn test_command_exists_injection() { | ||||||||||||||||||
| assert!(!super::command_exists("ls; echo injected")); | ||||||||||||||||||
| assert!(!super::command_exists("ls && echo injected")); | ||||||||||||||||||
|
Comment on lines
+5371
to
+5372
|
||||||||||||||||||
| assert!(!super::command_exists("ls; echo injected")); | |
| assert!(!super::command_exists("ls && echo injected")); | |
| assert!(!super::command_exists( | |
| "nonexistentcommandthatshouldneverexist123; echo injected" | |
| )); | |
| assert!(!super::command_exists( | |
| "nonexistentcommandthatshouldneverexist123 && echo injected" | |
| )); |
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_command_exists_injection only asserts the result is false. That can be a weak regression test because it would still pass even if the vulnerable code executed the injected portion but ultimately returned non-zero, and it could theoretically fail if an executable with that literal name exists in PATH. Consider asserting a side effect does not occur (e.g., try "sh; touch <tmpfile>" / "sh && touch <tmpfile>" and verify the tmpfile was not created) to prove no extra commands are executed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
command_existsnow avoids string interpolation (good), but it still hard-depends on invokingsh. On systems withoutsh(notably native Windows), this will always returnfalse, causingdetect_powershell_shell()to report PowerShell missing even whenpwsh/powershellis present. Consider makingcommand_existscross-platform (e.g., PATH scan in Rust and/or a Windows-specific implementation usingwhere) or at leastcfg(unix)/cfg(windows)split so PowerShell detection works on Windows without MSYS/Git-Bash.