diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 9e7c8335f..66a1098ab 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -57,8 +57,18 @@ jobs: # No custom prompt: Claude performs the instructions in the @claude comment. - # Let summoned runs actually fix bugs: allow Bash so Claude can build/test - # and verify the change before it commits, plus enough turns to investigate. - # File edits (Edit/Write) and git push are handled by the action itself. - # Safe because the job `if` gate restricts this to OWNER/MEMBER/COLLABORATOR. - claude_args: '--allowedTools Bash --max-turns 30' + # Let summoned runs actually fix bugs: allow the repo's build/test/lint + # commands so Claude can verify the change before it commits, plus enough + # turns to investigate. File edits (Edit/Write) and git push are handled + # by the action itself. + # + # Bash is scoped to a curated allowlist rather than wide-open: the job `if` + # gate trusts the *commenter*, but @claude can be summoned on a fork PR + # (claude-code-review.yml even directs fork PRs here), so the checked-out + # PR content is potentially attacker-controlled. Scoping blocks prompt + # injection from steering Claude into arbitrary shell/network commands + # while this job holds the OAuth secret + write token. Keep `bash`/`sh`/ + # `curl`/`wget`/`eval` OUT of this list. + claude_args: >- + --allowedTools "Bash(git:*),Bash(cmake:*),Bash(ninja:*),Bash(make:*),Bash(ctest:*),Bash(python3:*),Bash(python:*),Bash(pre-commit:*),Bash(clang-format:*),Bash(codespell:*)" + --max-turns 30