Skip to content

agent-guard: Segment.raw is the whole compound command, not the segment's own text #1150

Description

@AmirF194

What's broken

split_segments() gives every Segment in a compound command (a && b, a; b, ...) the exact same raw text: the whole input string, not that segment's own text. guard_commit_trailer scans seg.raw for a Co-Authored-By: trailer, so a git commit with a completely clean message gets denied if any other segment on the same line happens to mention that phrase (a comment, a grep, an echo explaining the rule).

Which layer

tools/agent-guard/src/agent_guard/__init__.py, Segment.__init__ / split_segments() (around line 137 and 155-172). Segment's own docstring says raw is "the original text of the segment", but split_segments constructs every segment as Segment(current, command), passing the full, unsliced input each time.

How to reproduce

python3 -c "
import sys; sys.path.insert(0, 'tools/agent-guard/src')
from agent_guard import dispatch
print(dispatch('echo \"note: never add a Co-Authored-By: trailer\" && git commit -m \"clean fix, no trailer here\"'))
"

Expected vs actual

Expected: None (allow), since the commit's own message has no trailer.
Actual: the commit-trailer deny string, because seg.raw for the git commit segment is the entire compound command, including the unrelated echo segment's text.

Surface area

GuardContext.raw exposes the same field to skill-contributed guards.d guards, but a repo-wide grep shows only the bundled guard_commit_trailer currently reads .raw, so the fix's blast radius is that one guard.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions