From c044b5d65f2718f7a52d4fcd8772af00c1adebbf Mon Sep 17 00:00:00 2001 From: cliffhall Date: Fri, 1 May 2026 10:19:59 -0400 Subject: [PATCH 1/2] ci: gate claude.yml on author_association to skip unauthorized invokes Previously the workflow's `if:` only checked the event type and the presence of `@claude` in the body. The job would start for any commenter and only later fail when the action attempted privileged operations on behalf of a user without write access. That produced noisy red runs and wasted runner minutes for what is effectively an authorization rejection. Add an `author_association` check (OWNER, MEMBER, or COLLABORATOR) to each of the four trigger branches (issue_comment, pull_request_review_comment, pull_request_review, issues), so the job is short-circuited at workflow evaluation time and never starts for unauthorized invokers. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/claude.yml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 9fdebc230..9c7ce3c8f 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -14,10 +14,26 @@ jobs: claude: if: | ( - (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || - (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + (github.event_name == 'issue_comment' && + contains(github.event.comment.body, '@claude') && + (github.event.comment.author_association == 'OWNER' || + github.event.comment.author_association == 'MEMBER' || + github.event.comment.author_association == 'COLLABORATOR')) || + (github.event_name == 'pull_request_review_comment' && + contains(github.event.comment.body, '@claude') && + (github.event.comment.author_association == 'OWNER' || + github.event.comment.author_association == 'MEMBER' || + github.event.comment.author_association == 'COLLABORATOR')) || + (github.event_name == 'pull_request_review' && + contains(github.event.review.body, '@claude') && + (github.event.review.author_association == 'OWNER' || + github.event.review.author_association == 'MEMBER' || + github.event.review.author_association == 'COLLABORATOR')) || + (github.event_name == 'issues' && + (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) && + (github.event.issue.author_association == 'OWNER' || + github.event.issue.author_association == 'MEMBER' || + github.event.issue.author_association == 'COLLABORATOR')) ) runs-on: ubuntu-latest permissions: From 1bbf53cf76850b279ebd66faee8b27631a2b9f88 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Fri, 1 May 2026 10:49:54 -0400 Subject: [PATCH 2/2] ci: collapse author_association OR chains into contains(fromJSON(...)) Per review feedback on PR #1270: replace the three-way `==` OR chain in each of the four trigger branches with a single contains(fromJSON(...)) check against a shared list. Same semantics, less duplication, and the allowed-roles list is now defined once per branch instead of three times. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/claude.yml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 9c7ce3c8f..8aa4ba71a 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -16,24 +16,16 @@ jobs: ( (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') && - (github.event.comment.author_association == 'OWNER' || - github.event.comment.author_association == 'MEMBER' || - github.event.comment.author_association == 'COLLABORATOR')) || + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') && - (github.event.comment.author_association == 'OWNER' || - github.event.comment.author_association == 'MEMBER' || - github.event.comment.author_association == 'COLLABORATOR')) || + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)) || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && - (github.event.review.author_association == 'OWNER' || - github.event.review.author_association == 'MEMBER' || - github.event.review.author_association == 'COLLABORATOR')) || + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.review.author_association)) || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) && - (github.event.issue.author_association == 'OWNER' || - github.event.issue.author_association == 'MEMBER' || - github.event.issue.author_association == 'COLLABORATOR')) + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.issue.author_association)) ) runs-on: ubuntu-latest permissions: