fix(approval): gate git config write operations behind approval - #72576
fix(approval): gate git config write operations behind approval#72576nuffin wants to merge 3 commits into
Conversation
761600f to
069cf18
Compare
teknium1
left a comment
There was a problem hiding this comment.
Thanks for addressing the unprompted Git-identity write path. Current main still lacks a git config rule in tools/approval.py:606-866, and detect_dangerous_command() relies on that list at tools/approval.py:2049-2058, so the direct report remains valid.
Problems
- The added rule at
tools/approval.py:824only accepts an optional scope flag followed immediately by two non-flag tokens. It misses mutating forms such asgit config --add …,git config --replace-all …,git config --unset …, andgit config --remove-section …; these can still write or remove Git configuration without approval. - Commit
069cf180d05b5c206fe0eda80f86bf74461e3797adds no regression coverage for the new rule.
Suggested changes
- Cover Git's mutating config forms while keeping query-only forms (
--list,--get, bare keys) outside the approval gate. - Add focused positive and negative detection tests in the approval suite.
Automated hermes-sweeper review.
|
Both issues fixed:
|
069cf18 to
174fda3
Compare
SummaryOne PR directly addresses issue #72556. #72576 adds approval gating for ordinary and flag-based mutating Related pull requests
Suggested consolidationKeep #72576 open with a salvage path: preserve its approval rule for direct key/value writes and the newly covered mutating flags, while correcting Complex graphflowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
I72556(["issue #72556 (open)"])
P72576["PR #72576 (open)"]
P72576 -->|best fix| I72556
class I72556 open
class P72576 open
class P72576 best
class P72576 target
click I72556 "https://github.com/NousResearch/hermes-agent/issues/72556"
click P72576 "https://github.com/NousResearch/hermes-agent/pull/72576"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label). Cross-PR triage: Reviewed 1 pull request and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 4 kB of PR diffs, 8 kB of issue/PR text, 2 kB of discussion (4 comments), 2 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
71d23b6 to
3b105b0
Compare
Triage follow-up:
|
3b105b0 to
b347d0c
Compare
|
suggesting changes Several valid Git configuration mutations are not recognized as dangerous. The new detector covers only a limited ordering of scope, action, and operands. Option-bearing forms, attached file scopes, and edit mode remain classified as safe, so untrusted automation can bypass the approval gate while changing repository or global settings. Broaden parsing to follow Git argument semantics and add regression coverage while preserving read-only queries as safe. Security evidence: Review setup: I reviewed a run-owned local rebase or patch replay against current GitHub Not checked:
Signed: GPT-5.6-luna-max in Codex |
Add "git config <key> <value>" (with optional scope flag) to DANGEROUS_PATTERNS so the agent cannot silently set its own git identity. Read-only forms (--list, --get, bare key) are not gated. Closes NousResearch#72556.
…tion Replace narrow pattern matching only 'git config key value' with one covering --add, --replace-all, --unset, --unset-all, --remove-section, and --rename-section. Query-only forms (--list, --get, bare key) still pass through without approval. Add 8 regression tests: positive for all mutating forms, negative for all query forms. 98/98 approval tests pass.
The --file flag differs from --local/--global/--system/--worktree: it consumes a path argument. The old regex treated --file as an argumentless scope flag, so 'git config --file .gitconfig user.name' (a read-only key query) was misclassified as a dangerous write. Restructured the scope group: --file now has its own sub-pattern that consumes the path (--file \s+\S+\s+), while the other scope flags remain in the optional argumentless group. Added test_file_scoped_write_is_dangerous and test_file_scoped_read_is_safe to cover file-scoped writes and reads.
b347d0c to
ea60753
Compare
What does this PR do?
Adds
git config <key> <value>write operations toDANGEROUS_PATTERNSso the agent must ask before silently writing to.git/config.Related issues
Fixes #72556.
Type of change
What has changed
One new pattern in
tools/approval.pyDANGEROUS_PATTERNS, inserted after the existinggit push --forcepatterns. The regex requires a key and value (two non-flag positional arguments) so read-only forms like--list,--get, and bare-key queries are NOT gated.Matches:
git config user.name "foo",git config --global user.email "bar",git config --local core.editor vim.Does not match:
git config --list,git config --get user.name,git config user.name.How has this been tested?
Platforms tested
Checklist