From ac3e99358252d57300510dd50fe406b343685844 Mon Sep 17 00:00:00 2001 From: Amir Fathi Date: Sat, 5 Sep 2026 13:07:32 +0000 Subject: [PATCH] fix(agent-guard): scope Segment.raw to its own tokens, not the whole command split_segments() passed the entire compound command as `raw` for every segment it produced, so guard_commit_trailer's Co-Authored-By scan could fire on a segment whose own text never mentioned it. raw is now shlex.join(current), a reconstruction of that segment's own tokens. Fixes #1150 Generated-by: Claude Code (Sonnet 5) --- tools/agent-guard/src/agent_guard/__init__.py | 8 ++++---- tools/agent-guard/tests/test_guards.py | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/agent-guard/src/agent_guard/__init__.py b/tools/agent-guard/src/agent_guard/__init__.py index 3f28dfb18..6cb62e0aa 100644 --- a/tools/agent-guard/src/agent_guard/__init__.py +++ b/tools/agent-guard/src/agent_guard/__init__.py @@ -113,8 +113,8 @@ class Segment: """One simple command from a (possibly compound) shell line. ``argv`` has leading ``NAME=value`` env assignments stripped into ``env``; - ``raw`` is the original text of the segment (used for substring scans that - survive heredocs, e.g. the Co-Authored-By trailer). + ``raw`` is a reconstruction of this segment's own tokens only (used for + substring scans that survive heredocs, e.g. the Co-Authored-By trailer). """ def __init__(self, tokens: list[str], raw: str) -> None: @@ -164,12 +164,12 @@ def split_segments(command: str) -> list[Segment]: for tok in tokens: if tok in SHELL_OPERATORS: if current: - segments.append(Segment(current, command)) + segments.append(Segment(current, shlex.join(current))) current = [] else: current.append(tok) if current: - segments.append(Segment(current, command)) + segments.append(Segment(current, shlex.join(current))) return segments diff --git a/tools/agent-guard/tests/test_guards.py b/tools/agent-guard/tests/test_guards.py index cb864a7ec..9ac485ebb 100644 --- a/tools/agent-guard/tests/test_guards.py +++ b/tools/agent-guard/tests/test_guards.py @@ -218,6 +218,13 @@ def test_compound_command_guarded(): assert dispatch('cd /tmp && git commit -m "x\nCo-Authored-By: a"') is not None +def test_compound_command_other_segment_not_denied(): + # The phrase lives in an unrelated earlier segment, not in the commit's + # own message, so the commit segment must not inherit it. + command = 'echo "note: never add a Co-Authored-By: trailer" && git commit -m "clean fix"' + assert dispatch(command) is None + + def test_malformed_command_allows(): assert dispatch('gh pr comment 5 --body "oops') is None