Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 29 additions & 20 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,36 @@ on:
jobs:
claude:
name: Claude Code Action
# Security: Only allow invocation by trusted contributors.
# Blocks NONE (anonymous), FIRST_TIMER, and FIRST_TIME_CONTRIBUTOR to
# prevent prompt-injection attacks from untrusted GitHub users.
# Security: only allow invocation by trusted contributors.
#
# This is an allow-list rather than a deny-list. Denying NONE, FIRST_TIMER
# and FIRST_TIME_CONTRIBUTOR still admitted CONTRIBUTOR — which anyone
# earns permanently by getting a single pull request merged — and
# MANNEQUIN. This job holds contents: write and ANTHROPIC_API_KEY and
# allows Bash(git *), so the bar needs to be write access to the
# repository, not a history of contributing to it.
#
# Same pattern as the /retest gate in retest.yaml.
# See: https://docs.github.com/en/graphql/reference/enums#commentauthorassociation
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') &&
github.event.comment.author_association != 'NONE' &&
github.event.comment.author_association != 'FIRST_TIMER' &&
github.event.comment.author_association != 'FIRST_TIME_CONTRIBUTOR') ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') &&
github.event.comment.author_association != 'NONE' &&
github.event.comment.author_association != 'FIRST_TIMER' &&
github.event.comment.author_association != 'FIRST_TIME_CONTRIBUTOR') ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') &&
github.event.review.author_association != 'NONE' &&
github.event.review.author_association != 'FIRST_TIMER' &&
github.event.review.author_association != 'FIRST_TIME_CONTRIBUTOR') ||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude') &&
github.event.issue.author_association != 'NONE' &&
github.event.issue.author_association != 'FIRST_TIMER' &&
github.event.issue.author_association != 'FIRST_TIME_CONTRIBUTOR')
if: >-
${{
(github.event_name == 'issue_comment'
&& contains(github.event.comment.body, '@claude')
&& contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'),
github.event.comment.author_association))
|| (github.event_name == 'pull_request_review_comment'
&& contains(github.event.comment.body, '@claude')
&& contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'),
github.event.comment.author_association))
|| (github.event_name == 'pull_request_review'
&& contains(github.event.review.body, '@claude')
&& contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'),
github.event.review.author_association))
|| (github.event_name == 'issues'
&& contains(github.event.issue.body, '@claude')
&& contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'),
github.event.issue.author_association))
}}
runs-on: ubuntu-latest
timeout-minutes: 20
# Least-privilege permissions for the AI agent workflow.
Expand Down
Loading