The Claude review check skips pull requests from forks instead of failing on them - #82
Merged
Merged
Conversation
…ling on them
GitHub gives a `pull_request` run of fork code neither the repository secrets nor an OIDC token, so anthropics/claude-code-action fails inside its GitHub-token setup ("Could not fetch an OIDC token") before Claude ever starts. Every contributor PR since #77 has carried a red claude-review check for that reason alone; the workflow itself has not changed since August. Gate the job on the head repository being this one, so fork PRs show the check as skipped and same-repo branches keep their review.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every pull request from a fork has carried a red
claude-reviewcheck since #77; the review job now skips fork PRs, so the check reads "skipped" instead of "failure" and same-repo branches are reviewed exactly as before.Contents: 🐛 Symptom · 🔍 Cause · ✅ Fix · 📸 Before / After · 🔁 State ·⚠️ Risk · 🔧 Technical overview · 🧪 Proof · 📝 Notes
🐛 Symptom
Three contributor PRs in a row (#77, #79, #81) showed a failing
claude-reviewcheck, while PRs opened from branches in this repository (#75, #80) passed the same day. Each failing run died about 25 seconds in, at the "Run Claude Code Review" step, before Claude had read a line of the diff. Re-running the job did not help: #81 failed three times in five minutes.🔍 Cause
The workflow runs on
pull_request. When the head branch lives in a fork, GitHub runs that workflow with a read-only token, no repository secrets, and no OIDC token: theid-token: writepermission in the file is simply not honoured for foreign code.anthropics/claude-code-actionasks for an OIDC token first, to mint its GitHub App token, and gives up after three attempts withCould not fetch an OIDC token. Nothing in.github/workflows/had changed since 2026-08-28; what changed on 2026-09-15 is that the first fork PRs arrived.✅ Fix
if: github.event.pull_request.head.repo.full_name == github.repository, so a PR whose head is in another repository shows the check as skipped, not failed.@claudecomment workflow and the release workflow are not touched.📸 Before / After
There is no screen to shoot: the change is a condition on a CI job. The terminal shows it instead.
Before — the tail of run 35062940588 on #81, identical on #77 and #79:
After — this PR's own run (35103634141) gets past the step that killed the fork runs, then stops on purpose because the PR edits the review workflow itself:
The next fork PR will list the check as
SKIPPEDinstead ofFAILURE.🔁 State
flowchart LR PR[pull_request event] --> Q{head repo == this repo?} Q -- yes --> RUN[Run Claude Code Review] RUN --> OIDC[fetch OIDC token] --> REVIEW[inline review comments] Q -- "no, before" --> RUN2[Run Claude Code Review] RUN2 --> FAIL["no OIDC token → ❌ failure"] Q -- "no, after" --> SKIP["job skipped → ⏭ skipped"] style FAIL stroke:#c0392b,stroke-width:2px style SKIP stroke:#27ae60,stroke-width:2pxVerdict: 🟢 Low risk — the change removes a job run and adds nothing that executes.
pull_request_target, was rejected because it runs with this repository's secrets against untrusted PR content.if:in a workflow file; nothing in the daemon or TUI changes.if:slot as a commented "Filter by PR author" block; this fills it with the condition the template anticipated.Rollback:
git revertof the merge restores the red check on fork PRs; there is no protocol, store or pushed branch to undo.🔧 Technical overview
.github/workflows/claude-code-review.yml— theclaude-reviewjob had noif:, so it ran for everypull_requestevent; it now runs only whengithub.event.pull_request.head.repo.full_nameequalsgithub.repository, the standard GitHub Actions test for "not a fork".pull_request_target. It runs with the base repository's secrets, so a fork PR could steer the reviewer at theCLAUDE_CODE_OAUTH_TOKEN; the action's own security docs warn against checking out untrusted refs under it.github_token: ${{ secrets.GITHUB_TOKEN }}. On a fork PR that token is read-only and the OAuth secret is absent anyway, so the run would fail one step later instead.🧪 Proof
claude-reviewcheck is green, but trivially: the action refuses to review a PR that changes its own workflow file, so it exits 0 after the OIDC exchange succeeds. The exchange succeeding is the part the fork runs never reached.claude-reviewas skipped rather than failed.make cinot run: the diff is one YAML file, no Rust is touched.📝 Notes
main.🤖 Generated with Claude Code