Skip to content

feat(review): enforce reviewer read-only via tool allowlist#2194

Open
neversettle17-101 wants to merge 1 commit into
mainfrom
feat/reviewer-readonly-tool-allowlist
Open

feat(review): enforce reviewer read-only via tool allowlist#2194
neversettle17-101 wants to merge 1 commit into
mainfrom
feat/reviewer-readonly-tool-allowlist

Conversation

@neversettle17-101

Copy link
Copy Markdown
Collaborator

Ported from aoagents/ReverbCode#278.

Summary

The reviewer's read-only guarantee was enforced only by the prompt. This makes it an enforced sandbox by launching the reviewer off bypassPermissions (which skips the permission system and ignores allow/deny rules) with a scoped tool allowlist.

  1. ports.LaunchConfig gains AllowedTools []string / DisallowedTools []string. Empty = unrestricted, so worker sessions are unaffected.
  2. claude-code agent adapter plumbs them to --allowedTools / --disallowedTools. Each list is comma-joined into one value so a rule containing spaces (e.g. Bash(git diff:*)) is not split into separate tool names.
  3. Reviewer adapter launches in the default auto mode (off bypass) with:
    • allow: Read, Grep, Glob, Bash(gh:*), Bash(git diff:*), Bash(git log:*), Bash(git show:*), Bash(git status:*), Bash(ao review submit:*)
    • deny (defense in depth): Edit, Write, NotebookEdit, Bash(git push:*), Bash(git commit:*)

Port note

ReverbCode#278 also added ao review submit --body-text and rewrote the reviewer prompt so the verdict was recorded inline rather than written to review.md (to avoid granting Write). This repo already solves that differently — ao review submit --body - reads the body from stdin and the prompt already instructs the reviewer to stay read-only — so those two files are intentionally not ported. Only the tool-allowlist enforcement is brought over.

Test

  • go build ./..., go vet, gofmt — all clean.
  • go test ./internal/adapters/agent/claudecode/... ./internal/adapters/reviewer/claudecode/... ./internal/cli/... — pass.
  • New tests: agent-adapter flag emission (joined values; omitted when unset) and a hermetic reviewer test (off-bypass + correct allow/deny lists, no claude binary needed).

Notes

  • Accepted stall risk (as in Add Composio banner to README #278): the reviewer pane is headless. Off bypass, a tool that is neither allowed nor denied prompts — with no one to answer, it stalls. The scoped Bash allowlist means an unlisted bash command (cat, rg, ls) would stall. Worth an end-to-end review run to confirm the allowlist is permissive enough.

🤖 Generated with Claude Code

The reviewer's read-only guarantee was enforced only by the prompt. Add
AllowedTools/DisallowedTools to ports.LaunchConfig and plumb them through
the claude-code agent adapter to --allowedTools/--disallowedTools (each list
comma-joined into one value so a rule containing spaces like "Bash(git
diff:*)" is not split into separate tool names). Empty lists emit nothing, so
worker sessions are unaffected.

Launch the reviewer off bypassPermissions (which skips the permission system
and ignores allow/deny rules) in the default auto mode, with an allowlist
scoped to Read/Grep/Glob and the few Bash commands a reviewer needs (gh, git
diff/log/show/status, ao review submit) and an explicit deny list for
Edit/Write/NotebookEdit/git push/git commit as defense in depth.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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