Skip to content

feat(gh): proxy gh pr diff/checks, gh run list/view/rerun, allowlisted read-only gh api#39

Merged
madarco merged 3 commits into
mainfrom
feat/gh-relay-proxy
Jun 1, 2026
Merged

feat(gh): proxy gh pr diff/checks, gh run list/view/rerun, allowlisted read-only gh api#39
madarco merged 3 commits into
mainfrom
feat/gh-relay-proxy

Conversation

@madarco
Copy link
Copy Markdown
Owner

@madarco madarco commented Jun 1, 2026

Summary

Extends the in-box gh relay proxy (host runs the authenticated gh; the box never sees a token) with three capabilities agents frequently need, following the existing five-layer gh pr pattern (bash shim → ctl → relay allowlist → docker + cloud dispatch).

  • gh pr diff / gh pr checks — read-only additions to the existing gh.pr.* family (no prompt). Branch-injected like gh pr view.
  • gh run list / view / rerun — new gh.run.* family. list/view are silent reads; rerun re-triggers CI and is gated by the host confirm prompt (+ cloud AGENTBOX_GH_NO_SUB no-subscriber handling). gh run watch is deliberately not proxied (it blocks until CI finishes, which doesn't fit the buffered request/response model) — the shim rejects it with a pointer to gh run view.
  • Read-only gh api — restricted to an allowlist of endpoint patterns (GH_API_ALLOWED_ENDPOINTS, seeded with repos/:owner/:repo/pulls/:number/comments, designed to grow). Mutating calls are rejected three ways: at the shim, and server-side via refuseGhApiWrite (catches -X/--method non-GET and the field flags that auto-POST) + the endpoint allowlist.

Both dispatch paths updated — docker (server.ts) and cloud (host-actions.ts) — per the "fix across all providers" convention.

Also includes a host-CLI fix: agentbox git pr builds its subcommands by iterating GH_PR_OPS, so diff/checks were added to PR_OP_DESCRIPTIONS (otherwise commander's .description(undefined) acts as a getter and the CLI crashes at startup).

Scope decisions (confirmed)

  • Skip gh run watch; gh api GET-only to start; in-box surface only (no host-side agentbox gh run/api <box> convenience commands — these ops are read-mostly).

Help grouping cleanup

Second commit folds the orphan top-level commands (git, vercel, doctor) into the Advanced group in agentbox --help, removing the fail-soft "Other" section. The help drift test's buildProgram() was missing those three (which is why the drift went unnoticed) — now registered so the "no Other group" guard actually covers them.

Test plan

  • pnpm build green; pnpm lint clean; tsc --noEmit (apps/cli) clean.
  • relay 139/139, ctl 183/183, help 4/4 (incl. drift guard).
  • New unit tests: relay gh.test.ts (run ops, api endpoint + write guards), host-actions.test.ts routing, ctl gh-and-shims.test.ts (shim branch-injection / rejection cases).
  • node apps/cli/dist/index.js loads; git pr --help lists diff/checks; --help shows no "Other" group.
  • Live end-to-end against a real box with gh auth on the host (docker + a cloud provider) — not yet run.

🤖 Generated with Claude Code


Note

Medium Risk
Expands the GitHub CLI proxy (including CI rerun prompts) but keeps mutations gated and gh api narrowly allowlisted with write guards at shim and relay.

Overview
Extends the host-relayed gh proxy (box shim → agentbox-ctl → relay → host gh) so agents can inspect PRs and CI without host tokens in the box.

PR ops: Adds read-only gh pr diff and gh pr checks (no confirm prompt), with the same branch auto-injection as gh pr view. Host agentbox git pr picks up descriptions for these ops so Commander does not crash when iterating GH_PR_OPS.

Actions runs: New gh.run.list / view / rerun RPC family; list/view are silent reads, rerun is write-gated by the host confirm prompt (cloud path uses shared cloudWriteConfirm / AGENTBOX_GH_NO_SUB). gh run watch is intentionally not proxied (blocking); the shim errors and points at gh run view.

REST: Adds read-only gh api with a small endpoint allowlist (initially PR pull-request comments) plus refuseGhApiWrite (non-GET methods and field flags that auto-POST) enforced in the shim and relay. Docker server.ts and cloud host-actions.ts both dispatch the new RPCs.

CLI help: Moves git, doctor, and vercel into the Advanced help group and registers them in the help drift test so the Other bucket stays empty.

Reviewed by Cursor Bugbot for commit d38cde7. Configure here.

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agentbox-web Ready Ready Preview, Comment Jun 1, 2026 12:47pm

Request Review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d38cde7. Configure here.

Comment thread packages/relay/src/gh.ts
) {
return refuse(`field flag '${arg}' makes the request mutating`);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write guard misses combined short-flag forms like -XPOST

Medium Severity

refuseGhApiWrite checks arg === '-X' (exact match), so combined short-flag forms like -XPOST, -fkey=value, or -Fkey=value — which Go's pflag library (used by gh) typically accepts — bypass the server-side write guard entirely. The in-box shim's strict_flags catches these at the first layer, but the relay-side check is the last line of defense and can be reached directly via agentbox-ctl. The endpoint allowlist limits practical damage, but this is a gap in the stated defense-in-depth strategy.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d38cde7. Configure here.

…POST, -fkey=val)

Bugbot: refuseGhApiWrite used exact-match (arg === '-X'), so pflag's combined
short forms bypassed the relay-side guard. Recognize -X<value>/-X=<value> and
any -f*/-F* spelling. The box shim already rejected these; this closes the
direct-agentbox-ctl last-line-of-defense gap.
@madarco madarco merged commit 844e43b into main Jun 1, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant