Skip to content

fix(agentic-engineering): the forge guard denies gh api -X GET with field arguments #144

Description

@devantler

🤖 Generated by the Agentic Engineer

Evidence

forge-readonly-guard.sh denies gh api field arguments unconditionally:

gh api -X GET "repos/<o>/<r>/activity" -f per_page=100 -f "ref=refs/heads/main"
  -> deny: gh api field arguments make the request a POST

gh api --method GET "repos/<o>/<r>/activity" -f per_page=100
  -> deny: gh api field arguments make the request a POST

gh api -X GET search/issues -f q=org:devantler-tech --paginate
  -> deny: gh api field arguments make the request a POST

The stated reason is factually wrong when an explicit GET method is present. gh api documents
that adding parameters switches the method to POST unless --method GET is given, in which case
the parameters are serialised into the query string. So -X GET … -f k=v is a GET — a read —
and the guard's own contract ("is this provably a read against the source forge") should allow it.

Why this blocks #108

Two reads the surveyor definition prescribes use exactly this shape:

  • the push-recency repos/<o>/<r>/activity read that produces the active=pushed:… signal — the
    active-work test that decides whether a PR may be taken over;
  • the search/issues discovery census that produces the issue denominator.

Wiring the guard into a runtime today would therefore remove both. This is precisely the case the
plugin README warns about: "a read it does not yet recognise fails closed … better discovered
deliberately than mid-run."

Expected behaviour

Field arguments are permitted only when an explicit GET method is present; every other case keeps
its current denial.

Acceptance criteria

  • -f/--raw-field/-F/--field allowed when --method GET / -X GET is present (case-insensitive).
  • Bare -f with no method stays denied (gh defaults to POST).
  • -f with any non-GET method stays denied.
  • -F key=@file / @file stays denied by the existing file-read rule, including under -X GET
    — this is an independent protection and must not be widened.
  • --input stays denied.
  • graphql handling is unchanged.
  • RED/GREEN coverage for each of the above in forge-readonly-guard.test.sh.

⚠️ Authority note

This is a loosening of a security control's allowlist. The Agentic Engineer's contract reserves
guardrail loosenings to the maintainer, so this is filed with complete evidence and a bounded patch
shape rather than shipped as a PR by that role. The measured verification corpus that surfaced it is
.claude/scripts/surveyor-forge-vocabulary.test.sh in devantler-tech/monorepo, where these three
shapes are pinned as tracked gap entries that fail the moment they start being allowed.

Part of #108

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions