Skip to content

πŸ›‘οΈ Sentinel: [CRITICAL] Fix Git argument injection via branch name#71

Open
xbmc4lyfe wants to merge 1 commit into
mainfrom
sentinel-git-argument-injection-13106249361622343253
Open

πŸ›‘οΈ Sentinel: [CRITICAL] Fix Git argument injection via branch name#71
xbmc4lyfe wants to merge 1 commit into
mainfrom
sentinel-git-argument-injection-13106249361622343253

Conversation

@xbmc4lyfe
Copy link
Copy Markdown
Collaborator

🚨 Severity: CRITICAL
πŸ’‘ Vulnerability: Branch and base names fetched from remote sources or user input were being passed directly to git commands without validation. If a branch name started with a hyphen (e.g., -b), it could be interpreted as an argument by git commands like git worktree add, leading to Git argument injection.
🎯 Impact: An attacker could potentially execute arbitrary Git options, potentially altering the repository state maliciously or bypassing security controls.
πŸ”§ Fix: Added checks in _validate_pr_metadata to raise a CommandError if branch, pr_base, or expected_base start with a hyphen.
βœ… Verification: Ran syntax checks and the test suite. Ensure PYTHONPATH=. pytest tests/ -k "not test_main_signal_handler" passes.


PR created automatically by Jules for task 13106249361622343253 started by @xbmc4lyfe

Added validation checks in `_validate_pr_metadata` to ensure that `expected_base`, `pr_base`, and `headRefName` do not start with a hyphen. This prevents potential Git argument injection vulnerabilities when these values are passed to `git` commands (e.g., `git worktree add`).

Co-authored-by: xbmc4lyfe <273732874+xbmc4lyfe@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown

πŸ‘‹ 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 @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

Review Change Stack

πŸ“ Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Fixed a security vulnerability related to Git argument injection through branch and base names. Enhanced validation now rejects branch and base names starting with a hyphen, preventing them from being interpreted as command-line options or Git arguments.

Walkthrough

This PR adds defensive Git argument injection guards to the PR metadata validation function. The _validate_pr_metadata function now rejects branch and base names that start with - to prevent those values from being interpreted as command-line options when passed to Git. A changelog entry documents the fix.

Changes

Git Argument Injection Validation

Layer / File(s) Summary
Argument injection guards in PR metadata validation
ralph_loop/cli.py, .jules/sentinel.md
_validate_pr_metadata now validates expected_base, pr_base, and headRefName by rejecting values starting with - to prevent Git command argument injection. When pr_base is present, it also enforces that it matches expected_base. Sentinel documentation records the fix.

🎯 2 (Simple) | ⏱️ ~10 minutes

🐰 A hyphen-armed hare crept toward the Git,
But brave _validate stood firm and said "No hit!"
Branch names start clean, no dashes in sight,
Now arguments flow pure, safe, and quite right.
Sentinel marks this victory won. ✨

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (4 passed)
Check name Status Explanation
Title check βœ… Passed The title directly references the main security fixβ€”Git argument injection via branch namesβ€”and matches the changeset's core objective of adding defensive validation.
Description check βœ… Passed The description clearly explains the vulnerability, its impact, and the specific fix applied, all of which align with the changes in the PR.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sentinel-git-argument-injection-13106249361622343253
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch sentinel-git-argument-injection-13106249361622343253

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
ralph_loop/cli.py (1)

336-337: πŸ’€ Low value

Consider adding isinstance check for consistency and defensive coding.

Lines 356 and 368 use isinstance(value, str) before calling .startswith(), but line 336 calls .startswith() directly on expected_base. While expected_base comes from args.base (argparse) and should always be a string, adding the isinstance check would make the validation pattern consistent and more defensive.

πŸ›‘οΈ Proposed fix for consistency
-    if expected_base.startswith("-"):
+    if isinstance(expected_base, str) and expected_base.startswith("-"):
         raise CommandError("Git argument injection detected: base branch starts with a hyphen.")
πŸ€– 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 `@ralph_loop/cli.py` around lines 336 - 337, Add the same defensive isinstance
check used elsewhere before calling .startswith() on expected_base: verify that
expected_base (derived from args.base) is an instance of str before calling
expected_base.startswith("-"); if it's not a str, either skip the hyphen check
or raise the same CommandError. Update the validation around expected_base to
mirror the pattern used at the other checks (isinstance(value, str) then
.startswith()) so the code in ralph_loop/cli.py remains consistent and robust
against non-string inputs.
πŸ€– 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 `@ralph_loop/cli.py`:
- Around line 336-337: Add the same defensive isinstance check used elsewhere
before calling .startswith() on expected_base: verify that expected_base
(derived from args.base) is an instance of str before calling
expected_base.startswith("-"); if it's not a str, either skip the hyphen check
or raise the same CommandError. Update the validation around expected_base to
mirror the pattern used at the other checks (isinstance(value, str) then
.startswith()) so the code in ralph_loop/cli.py remains consistent and robust
against non-string inputs.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 663d1789-3189-4f19-a83c-457dfe5bee73

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 7b35ed2 and ea0f9d6.

πŸ“’ Files selected for processing (2)
  • .jules/sentinel.md
  • ralph_loop/cli.py
πŸ“œ Review details
πŸ”‡ Additional comments (3)
ralph_loop/cli.py (1)

336-337: LGTM!

Also applies to: 355-369

.jules/sentinel.md (2)

2-4: LGTM!


1-1: ⚑ Quick win

Verify .jules/sentinel.md entry date convention.

.jules/sentinel.md contains a single entry dated 2024-05-24 (β€œFix Git argument injection via branch name”), but there’s no in-repo convention/docs explaining whether sentinel dates are intentionally backdated or expected to match the PR timeline. Confirm the intended dating rule for sentinel entries.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ea0f9d63f7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ralph_loop/cli.py
Comment on lines +368 to +369
if isinstance(branch, str) and branch.startswith("-"):
raise CommandError("Git argument injection detected: PR head branch starts with a hyphen.")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the current branch before calling gh

When --pr is omitted, _resolve_pr_data() uses the current branch name as the gh pr view selector before this new headRefName guard ever runs. The gh pr view usage is gh pr view [<number> | <url> | <branch>] [flags] and includes inherited flags like --repo, so a current branch whose ref name starts with - can still be parsed as a gh option instead of being rejected here. Add the same hyphen check to the locally-derived pr_ref before _pr_view(pr_ref) is invoked.

Useful? React with πŸ‘Β / πŸ‘Ž.

Comment thread ralph_loop/cli.py
Comment on lines +336 to +337
if expected_base.startswith("-"):
raise CommandError("Git argument injection detected: base branch starts with a hyphen.")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the base before fan-out listing

This expected_base guard only runs after a specific PR has been resolved, but the --all-prs/implicit fan-out path calls _list_open_prs(args.base) first, which builds gh pr list --base <base> .... In that fan-out context, a --base=-... value still reaches the GitHub CLI before validation, so the new protection does not cover one of the CLI inputs it says it protects. Validate args.base before deciding/listing fan-out PRs, not only inside per-PR metadata validation.

Useful? React with πŸ‘Β / πŸ‘Ž.

Comment thread ralph_loop/cli.py
Comment on lines +368 to +369
if isinstance(branch, str) and branch.startswith("-"):
raise CommandError("Git argument injection detected: PR head branch starts with a hyphen.")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject leading plus refspecs

For a same-repository PR whose valid head branch starts with +, this guard still allows the value into _fetch_pr_branch_or_head, where git fetch origin +foo is parsed as a force refspec for foo rather than as the branch +foo. In a repo that already has origin/+foo, that leaves the PR tracking ref stale while Ralph proceeds from origin/+foo, so repairs/rebases can run against an old PR head. Treat leading + as unsafe here as well, or fetch by an explicit full refspec that cannot reinterpret the branch name.

Useful? React with πŸ‘Β / πŸ‘Ž.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant