Skip to content

fix(agents): three gh forms the reworked push gate still does not judge #797

Description

@EricAndrechek

Problem

The reworked push gate (the make ci-remote PR that closes #790) judges each gh pr / gh api call on its own, including code handed to a shell and code inside $(…). Review of that change found three forms it still does not judge. Each is less common than the forms the PR covers, so they were left for this follow-up rather than another round on that PR. The gate's stated goal is guarding against accidents, not deliberate workarounds.

Forms not judged

All three are inferred from reading .claude/hooks/agent-bash-gate.sh on that branch; none was run.

  1. -R / --repo between pr and its subcommand. gh pr -R o/r ready 12, gh pr --repo o/r create … and gh pr --repo=o/r review 12 --approve. The gate reads the first word after pr as the subcommand, here -R. Whether gh accepts the flag in that position is unverified (it is a persistent flag on gh pr, which suggests it does). The gate already handles -R before pr.
  2. Leftover code past the 64-piece cap, when the mention is quoted; and ${x:-$(…)}. Past the cap, leftover pieces are refused only if they match the gate's gh regex, which expects gh after start-of-line, whitespace or a separator, so a quoted 'gh pr ready' in a leftover piece (for example $(bash -c 'gh pr ready 12') as the 65th piece) is let through unjudged. Separately, a substitution inside a parameter-expansion default, ${x:-$(gh pr ready 12)}, is never queued, because its saved text starts with ${.
  3. -F query=@- or --input - fed by a heredoc on the same line. The body is on the command line, but values starting with @ are skipped. The gate's docs already list --input and -F field=@file as unseen, so this is a documented limit; the same-line heredoc case is the one the gate could read.

Related

#790, #787, #755, #740

Activity

  1. EricAndrechek commented on Oct 9, 2026

    @EricAndrechek
    MemberAuthor

    Five more forms from the final review of that branch, all pre-existing in the tokenizer rather than introduced by its last commit. Labels are the reviewer's: measured means run through the gate.

    1. << inside arithmetic swallows the following lines. n=$(( 1 << 3 )) followed on the next line by a guarded gh command or git push is allowed: the tokenizer registers the << as a heredoc and the pending delimiter 3 eats every later line. For the gh checks this is a regression against main's regex gate, which blocked it (measured). The push half existed on main already (inferred).
    2. The push check doesn't follow a heredoc a shell reads inside $(…) (out=$(bash <<'EOF' … git push … … EOF ) is allowed, measured), while the gh checks now do. The push check reads the body-less form of the substitution.
    3. An unquoted heredoc's body runs $(…), but neither check follows it (cat <<EOF / $(…) / EOF, measured). The "a mention in a heredoc body doesn't count" rule assumes a quoted delimiter.
    4. A computed query= is matched against the whole call, so another field's heredoc text naming a mutation trips it. A false positive on an unusual form.
    5. Nested escaped backticks aren't followed ( x=`echo \`…\ ``), before and after the change.

    — Posted by Claude Code on behalf of @EricAndrechek

  2. EricAndrechek commented on Oct 9, 2026

    @EricAndrechek
    MemberAuthor

    Two more from the review of the create-time reviewer/assignee block added to the same branch (both measured through the gate by the reviewer):

    1. A glued short-flag cluster led by another letter passes. On gh pr create, -fr alice or -fa alice (fill plus reviewer/assignee, as pflag reads it) is allowed, because the check matches only a token that starts with -r or -a. Covering any single-dash cluster containing r/a would also catch values the loop scans (see 7), so it needs care.
    2. A value starting with -a or -r on create is refused with the reviewer message, e.g. a -b "-a thing" body, because the loop scans value tokens as well as flags. Rare (markdown bullets are - x with a space) and loud rather than a bypass; the existing title handling has the same value-scanning shape.

    — Posted by Claude Code on behalf of @EricAndrechek

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

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions