🔒 fix potential argument injection in git commands#56
🔒 fix potential argument injection in git commands#56bashandbone wants to merge 1 commit intomainfrom
Conversation
Replaces the use of `-C <path>` with `.current_dir(path)` in `git read-tree` and adds `--` separator before the path argument in `git rm` to prevent malicious paths starting with hyphens from being interpreted as flags. Added `tests/security_tests.rs` to verify the fix and prevent regressions. Co-authored-by: bashandbone <[email protected]>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
There was a problem hiding this comment.
Pull request overview
This PR hardens git command invocations in the GitOpsManager fallback paths to prevent paths that begin with - from being parsed as git options, and adds integration tests intended to cover these cases.
Changes:
- Add
--terminator to thegit rm --cached ...cleanup command before the user-controlled submodule path. - Replace
git -C <path> ...withCommand::current_dir(<path>)for thegit read-treesparse-checkout CLI fallback. - Add a new
tests/security_tests.rsfile covering hyphen-prefixed path scenarios.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/git_ops/mod.rs |
Hardens CLI fallback git command construction against option/argument injection. |
tests/security_tests.rs |
Adds integration tests targeting hyphen-prefixed paths for submodule add and sparse checkout. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| mod common; | ||
| use common::TestHarness; | ||
| use std::fs; |
There was a problem hiding this comment.
Unused import: use std::fs; isn't referenced anywhere in this test file. Removing it will avoid warnings and keep the test focused.
| use std::fs; |
| let remote_url = format!("file://{}", remote_repo.display()); | ||
|
|
||
| // Path starting with hyphen | ||
| let path = "./-sparse"; |
There was a problem hiding this comment.
This test intends to validate behavior for a path that starts with a hyphen, but path is set to "./-sparse" (starts with .). Using "-sparse" (or an equivalent that preserves the leading - without a ./ prefix) would better exercise the injection scenario described in the PR.
| let path = "./-sparse"; | |
| let path = "-sparse"; |
| // A path starting with a hyphen that could be a git flag | ||
| let malicious_path = "-c"; | ||
|
|
||
| // This should not fail with "unknown option" or similar error from git -C | ||
| // It might still fail for other reasons if the path is invalid for a submodule, | ||
| // but it shouldn't be interpreted as a flag to the 'git' command itself. | ||
|
|
||
| // Note: Using add_submodule via harness. | ||
| // We need to make sure the directory doesn't exist or is handled. | ||
|
|
||
| let result = harness.run_submod(&[ | ||
| "add", | ||
| &remote_url, | ||
| "--name", | ||
| "hyphen-sub", | ||
| "--path", | ||
| malicious_path, | ||
| ]); | ||
|
|
||
| // The operation might fail because "-c" is a weird path, but it shouldn't be a Command Injection. | ||
| // If it was interpreted as `git -C -c`, it would fail with "unknown option: -c" or similar. | ||
|
|
||
| match result { | ||
| Ok(output) => { | ||
| let stderr = String::from_utf8_lossy(&output.stderr); | ||
| assert!(!stderr.contains("unknown option: -c"), "Potential command injection detected: git interpreted path as a flag"); | ||
| }, | ||
| Err(e) => { | ||
| let err_msg = e.to_string(); | ||
| assert!(!err_msg.contains("unknown option: -c"), "Potential command injection detected: git interpreted path as a flag"); | ||
| } | ||
| } |
There was a problem hiding this comment.
test_path_with_hyphen_injection can pass even if the submod add invocation fails for unrelated reasons (argument parsing, network, etc.), and it also doesn't ensure the failure path that runs the git rm --cached ... cleanup (where the new -- separator matters) is actually executed. Consider asserting a concrete expected outcome (e.g., command succeeds and the -c directory exists), or explicitly forcing the error/cleanup path and asserting it does not treat -c as an option.
| // A path starting with a hyphen that could be a git flag | |
| let malicious_path = "-c"; | |
| // This should not fail with "unknown option" or similar error from git -C | |
| // It might still fail for other reasons if the path is invalid for a submodule, | |
| // but it shouldn't be interpreted as a flag to the 'git' command itself. | |
| // Note: Using add_submodule via harness. | |
| // We need to make sure the directory doesn't exist or is handled. | |
| let result = harness.run_submod(&[ | |
| "add", | |
| &remote_url, | |
| "--name", | |
| "hyphen-sub", | |
| "--path", | |
| malicious_path, | |
| ]); | |
| // The operation might fail because "-c" is a weird path, but it shouldn't be a Command Injection. | |
| // If it was interpreted as `git -C -c`, it would fail with "unknown option: -c" or similar. | |
| match result { | |
| Ok(output) => { | |
| let stderr = String::from_utf8_lossy(&output.stderr); | |
| assert!(!stderr.contains("unknown option: -c"), "Potential command injection detected: git interpreted path as a flag"); | |
| }, | |
| Err(e) => { | |
| let err_msg = e.to_string(); | |
| assert!(!err_msg.contains("unknown option: -c"), "Potential command injection detected: git interpreted path as a flag"); | |
| } | |
| } | |
| // A path starting with a hyphen that could be a git flag. | |
| // This should be handled as a literal path component, not interpreted | |
| // as an option to git or to any cleanup command that operates on paths. | |
| let malicious_path = "-c"; | |
| harness.run_submod_success(&[ | |
| "add", | |
| &remote_url, | |
| "--name", | |
| "hyphen-sub", | |
| "--path", | |
| malicious_path, | |
| ]).expect("Failed to add submodule with hyphenated path"); | |
| // Verify the submodule was actually created at the requested path. | |
| assert!(harness.dir_exists("-c")); |
This PR fixes a potential command/argument injection vulnerability in
src/git_ops/mod.rs.🎯 What: The vulnerability fixed is a potential argument injection where unsanitized paths starting with a hyphen (e.g.,
-c) could be interpreted as flags to thegitcommand when using the-Coption or when passing paths togit rm.-c core.sshCommand=...could lead to arbitrary code execution if git interpreted it as a configuration flag.🛡️ Solution:
apply_sparse_checkoutfallback, replaced.args(["-C", path, ...])with.current_dir(path).args([...]). This ensures the directory is changed by the Rust process manager rather than by git's own flag parser, making it safe from injection.add_submodulecleanup, added the--separator before the path argument in thegit rmcommand. This is the standard way to signal the end of command options and ensure following arguments are treated as paths.tests/security_tests.rsthat specifically tests adding submodules and applying sparse checkout with paths that start with hyphens (e.g.,-cand./-sparse) to verify robustness.The fix was verified by manually confirming the command construction logic using a standalone Rust script, as the full integration test suite was partially blocked by environment-specific network timeouts during dependency resolution. The code review confirmed the approach as #Correct# and robust.
PR created automatically by Jules for task 3638338362005587233 started by @bashandbone