Guard Claude review workflow against non-collaborator PR authors#7761
Guard Claude review workflow against non-collaborator PR authors#7761
Conversation
Add author_association check to the pull_request trigger condition, matching the existing guard on issue_comment. Prevents the review from running on PRs opened by non-org-members (fork PRs on public repo), saving runner minutes and avoiding failed-check noise. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
Greptile SummaryThis PR adds a single-line
Confidence Score: 5/5Safe to merge — minimal, correct, security-improving change with no risk of breakage. The change is a one-line addition that mirrors an existing, already-working guard. The field reference and allowed-values list are correct for the GitHub Actions event payload. No existing behaviour for trusted authors is altered, and the security gap for fork PRs is properly closed. No files require special attention. Important Files Changed
Reviews (1): Last reviewed commit: "Add changelog entry for #7761" | Re-trigger Greptile |
| github.event_name == 'pull_request' | ||
| && !github.event.pull_request.draft | ||
| && github.actor != 'dependabot[bot]' | ||
| && contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.pull_request.author_association) |
There was a problem hiding this comment.
Did this change break it? I don't see the Claude review.
There was a problem hiding this comment.
thanks for calling this out. so it is expected that claude will abort the review if the workflow definition differs from what's on main, as a security measure - so i thought that's what was happening here.
but actually it looks like the entire workflow was skipped on the 'ready for review' action, which is not the way the above would surface: the workflow should instead be executing but the review step itself should fail with an informative error about how the workflow differs from main.
so it does look like there may be a bug here, let me see 👀
There was a problem hiding this comment.
for visibility, here's claude's analysis:
There's the bug. Your author_association on this PR is CONTRIBUTOR, not MEMBER or COLLABORATOR.
This is because author_association reflects your relationship to the repo, not the org. Since fides is a public/open-source repo, even org members who don't have direct collaborator permissions on the repo itself get classified as CONTRIBUTOR (meaning: has previously
had a PR merged).The fix is to add "CONTRIBUTOR" to the allowed list. But that partially defeats the purpose — external contributors who've had a PR merged would also get CONTRIBUTOR.
A better approach: use github.actor against the org membership instead, or just add CONTRIBUTOR since the real secret-protection comes from GitHub's fork PR secret isolation anyway. The author_association guard is defense-in-depth for runner minutes, and CONTRIBUTOR
still excludes totally unknown first-time PR authors (FIRST_TIME_CONTRIBUTOR, FIRST_TIME_COMMITTER, NONE).Let me update the guard:
Read 1 file (ctrl+o to expand)
:black_circle_for_record: Wait — let me reconsider the right approach here. The possible author_association values are:
┌────────────────────────┬──────────────────────────────────────┐
│ Value │ Meaning │
├────────────────────────┼──────────────────────────────────────┤
│ OWNER │ Owner of the repo │
├────────────────────────┼──────────────────────────────────────┤
│ MEMBER │ Member of the org that owns the repo │
├────────────────────────┼──────────────────────────────────────┤
│ COLLABORATOR │ Invited collaborator on the repo │
├────────────────────────┼──────────────────────────────────────┤
│ CONTRIBUTOR │ Has previously merged a PR │
├────────────────────────┼──────────────────────────────────────┤
│ FIRST_TIME_CONTRIBUTOR │ First PR to this repo │
├────────────────────────┼──────────────────────────────────────┤
│ FIRST_TIMER │ First PR on all of GitHub │
├────────────────────────┼──────────────────────────────────────┤
│ NONE │ No association │
└────────────────────────┴──────────────────────────────────────┘The fact that you're getting CONTRIBUTOR instead of MEMBER is surprising. You should be MEMBER as an org member. This might be a quirk of how the pull_request event payload populates author_association vs how the REST API returns it — or it could be that your org
membership visibility is set to private.Either way, the safest fix is to include CONTRIBUTOR in the PR trigger's allow-list. This still excludes FIRST_TIME_CONTRIBUTOR, FIRST_TIMER, and NONE — which are the actual threat vectors for the spend concern.
given this info, we're going to see what makes the most sense here...
Description Of Changes
Adds an
author_associationcheck to thepull_requesttrigger condition in the Claude Code Review workflow, matching the existing guard on theissue_commenttrigger. This prevents the review from running on PRs opened by non-org-members (e.g., fork PRs on this public repo).Why: The
issue_commenttrigger already gates on["OWNER","MEMBER","COLLABORATOR"]to prevent unauthorized spend. Thepull_requesttrigger lacked the same guard, meaning fork PRs could trigger workflow runs — wasting runner minutes, creating failed-check noise, and leaving the workflow vulnerable if it were ever refactored topull_request_target(which exposes secrets to fork PRs).Code Changes
.github/workflows/claude-code-review.yml- Addedauthor_associationcheck to thepull_requestcondition, using the same trusted set as the existingissue_commentguardSteps to Confirm
/code-reviewas an org member — should still work (unchanged path)Pre-Merge Checklist
CHANGELOG.mdupdatedmaindowngrade()migration is correct and works