diff --git a/.github/workflows/claude-pr-review.yml b/.github/workflows/claude-pr-review.yml index 28590db..08c6c79 100644 --- a/.github/workflows/claude-pr-review.yml +++ b/.github/workflows/claude-pr-review.yml @@ -13,7 +13,6 @@ jobs: contents: write pull-requests: write issues: write - id-token: write steps: - name: Check out PR head commit uses: actions/checkout@v4 @@ -22,7 +21,7 @@ jobs: fetch-depth: 0 - name: Run Claude on the review feedback - uses: anthropics/claude-code-action@v1 + uses: anthropics/claude-code-action@428971d2ecd6e3a7cb0ee0da2a3a8b33fdb3678d # v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} prompt: | diff --git a/tests/test_workflows_security.py b/tests/test_workflows_security.py new file mode 100644 index 0000000..3bec515 --- /dev/null +++ b/tests/test_workflows_security.py @@ -0,0 +1,22 @@ +"""Security regression tests for GitHub Actions workflows.""" + +from __future__ import annotations + +import re +from pathlib import Path + +WORKFLOW = Path(".github/workflows/claude-pr-review.yml") + + +def test_claude_pr_review_uses_immutable_action_pin() -> None: + workflow = WORKFLOW.read_text() + + match = re.search(r"uses:\s*anthropics/claude-code-action@([0-9a-f]{40})\b", workflow) + + assert match is not None + + +def test_claude_pr_review_does_not_request_oidc_token() -> None: + workflow = WORKFLOW.read_text() + + assert not re.search(r"^\s*id-token:\s*write\s*$", workflow, re.MULTILINE)