fix(ci): opt in to fork PR checkout so Claude review stops failing - #1715
Conversation
A recent actions/checkout v7 patch made the action hard-refuse a fork PR head under `pull_request_target` unless `allow-unsafe-pr-checkout: true`. Since every external PR is cross-repository, the review job started failing at the checkout step within seconds — including for known CONTRIBUTOR authors, who are exactly the ones the job's `if:` gate lets through automatically. Nothing changed on our side; the mutable `v7` tag moved under us. The guard targets "pwn request": checking out fork code and then executing it with the base repo's write-scoped token and secrets. This job never installs, builds, tests, or otherwise executes the checkout — it only reads it via Claude's Read/Grep/Glob, which is the whole reason the head is checked out. The token is already kept out of .git/config (persist-credentials: false) and out of the agent's subprocesses (the action's env scrub), and the agent has no Bash tool at all. So opt in explicitly, and record in a comment that this holds only while no step in this job executes the checkout.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe review workflow now checks out fork pull-request heads with ChangesReview workflow checkout
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR updates the Claude Code Review GitHub Actions workflow to opt in to checking out fork PR heads under pull_request_target, unblocking automated reviews for external contributors after a recent actions/checkout@v7 patch introduced a safety guard.
Changes:
- Set
allow-unsafe-pr-checkout: trueon theactions/checkout@v7step that checks out the PR head SHA for review context. - Add an in-file security rationale documenting why the opt-in is considered safe for this specific job and what invariants must remain true (no executing code from the checkout).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
🔍 Cloudflare PR preview
|
| # This stays true only as long as no step in this job executes the | ||
| # checkout. Do not add a build, install, or test step here — put it in | ||
| # ci.yml, which runs under `pull_request` and gets no secrets. | ||
| allow-unsafe-pr-checkout: true |
There was a problem hiding this comment.
Security (medium confidence): The safety argument above (no npm ci/build/test/lifecycle-script execution, no Bash tool) covers the classic "pwn request" path, but there's a second execution path it doesn't address: Claude Code's own hook mechanism. If the checked-out fork head (which is exactly what this opt-in now allows onto disk) contains a .claude/settings.json or .claude/settings.local.json with PreToolUse/PostToolUse hooks matching Read/Grep/Glob, those hooks run as shell commands automatically — hook execution isn't gated by --allowedTools, so excluding Bash from the agent's tool list doesn't stop it. A PR could add such a file in the very diff being reviewed and get arbitrary command execution in the runner during this step, even though GITHUB_TOKEN itself is scrubbed from subprocess env.
Worth confirming (and ideally noting in the comment here) that claude-code-action either ignores repo-local hook config or runs Claude Code with an isolated settings scope when reviewing untrusted fork content — otherwise this residual vector isn't covered by the reasoning given.
Also worth double-checking (lower confidence): that allow-unsafe-pr-checkout is genuinely a supported input on the pinned actions/checkout@v7 release. If the input name is off, GitHub Actions will typically just warn about an unrecognized input rather than fail the step, so the original checkout refusal would silently persist rather than being fixed — the PR's own verification notes it hasn't yet been confirmed against a fork PR run.
Code reviewBugs
Security
Performance
Quality
CLAUDE.md
|
Problem
Every Claude Code Review run on an external PR fails within seconds at the checkout step:
Example: run 31022945517 on #1714.
Nothing changed in this repo. A recent
actions/checkoutv7 patch release added this guard, and@v7is a mutable tag, so it moved under us. Because every external PR is cross-repository, this hits all of them — including knownCONTRIBUTORauthors, who are precisely the ones the job'sif:gate is meant to review automatically.Fix
Set
allow-unsafe-pr-checkout: trueon that one checkout step.Why that is safe here
The guard exists to stop "pwn request": a workflow that checks out fork code and then executes it —
npm ci, a build, a test, an npm lifecycle script — with the base repository's write-scopedGITHUB_TOKENand secrets.This job does none of that. It never installs dependencies, never builds, never tests, and never runs anything from the checkout. The head is only ever read, by Claude's
Read/Grep/Glob— which is the entire reason it is checked out (the base ref alone would hide added files and show pre-change context). Layered on top of that, already in place before this PR:persist-credentials: falsekeeps the token out of.git/config.allowed_non_write_users) stripsGITHUB_TOKEN/GH_TOKENfrom every subprocess the agent spawns.--allowedToolsgrants no Bash tool, so the agent has no way to execute the checked-out code even if a prompt injection told it to.The step comment records the invariant this rests on: it holds only while no step in this job executes the checkout. Build/install/test steps belong in
ci.yml, which runs underpull_requestand gets no secrets.Verification
The workflow parses and the input name matches
actions/checkout'saction.yml:pre-commit run --files .github/workflows/claude-code-review.ymlpasses. End-to-end confirmation is the next fork PR's review run going green — this PR is same-repo, so it does not exercise the fork path itself.Note:
pr-preview.ymlis the repo's only otherpull_request_targetworkflow, and it is unaffected — it checks out the default branch with noref:, so it never touches fork code.Summary by CodeRabbit