From c962332b31ea3ac1ca400f4ca696e6a30a80cac8 Mon Sep 17 00:00:00 2001 From: Chris Burns <29541485+ChrisJBurns@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:41:26 +0100 Subject: [PATCH] Suppress four zizmor findings that cannot be fixed Two dangerous-triggers findings flag the workflow_run trigger itself, which neither workflow can drop: applying a label needs write access the calculating workflow deliberately lacks, and claude-code-action rejects the release event. What made the first dangerous was trusting the artifact for the target pull request and the label, and neither is read from it any more. The second checks out the default branch rather than an event-supplied ref. Two artipacked findings are on checkouts that keep their credentials on purpose. claude.yml has contents: write so Claude can push commits, and that push uses the credential. api-compat.yml cannot push, but it runs a git fetch and is the only required status check, so dropping it risks blocking every pull request to clear one low-severity finding. Each suppression carries the reasoning inline, so the decision sits next to the code rather than only in an issue. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/api-compat.yml | 9 ++++++++- .github/workflows/claude.yml | 7 ++++++- .github/workflows/pr-size-label-apply.yml | 12 +++++++++++- .github/workflows/release-notes.yml | 9 ++++++++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.github/workflows/api-compat.yml b/.github/workflows/api-compat.yml index 6fcbdfe8d1..5c270e0efa 100644 --- a/.github/workflows/api-compat.yml +++ b/.github/workflows/api-compat.yml @@ -49,8 +49,15 @@ jobs: # bound that protects against a hung go install or git fetch. timeout-minutes: 10 steps: + # Left persisting credentials deliberately. This job cannot push — it has + # contents: read — so the exposure is limited, and it runs + # `git fetch origin refs/tags/...` below. That fetch succeeds + # unauthenticated only because this repository is public; dropping the + # credential would make it depend on that staying true. This job is also + # the repository's only required status check, so breaking it blocks + # every pull request. Not worth it to clear one low-severity finding. - name: Checkout PR HEAD - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 # zizmor: ignore[artipacked] - name: Set up Go uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 2a89ca1885..d339838bdc 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -54,8 +54,13 @@ jobs: id-token: write actions: read # Required for Claude to read CI results on PRs steps: + # Unlike every other checkout in this repository, this one keeps its + # credentials on purpose. The job holds contents: write precisely so + # Claude can push commits to a pull request, and that push uses the + # credential actions/checkout leaves in .git/config. Setting + # persist-credentials: false here would break the action. - name: Checkout repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 # zizmor: ignore[artipacked] with: fetch-depth: 1 diff --git a/.github/workflows/pr-size-label-apply.yml b/.github/workflows/pr-size-label-apply.yml index 5c94faa490..71f8f531db 100644 --- a/.github/workflows/pr-size-label-apply.yml +++ b/.github/workflows/pr-size-label-apply.yml @@ -1,7 +1,17 @@ name: PR Size Labeler - Apply on: - workflow_run: + # The `workflow_run` trigger is what makes this workflow privileged, and it + # cannot be removed — applying a label needs write access that the calculate + # workflow, running on `pull_request`, deliberately does not have. + # + # What made that dangerous was trusting the artifact: the pull request number + # and the label were both read out of it, and the artifact is produced by a + # workflow the pull request author controls, forks included. Neither is now. + # The number is derived from this workflow's own event and the label must + # match a fixed list of five values, so nothing crossing the boundary can + # decide which pull request is acted on or what is applied to it. + workflow_run: # zizmor: ignore[dangerous-triggers] workflows: ["PR Size Labeler - Calculate"] types: [completed] diff --git a/.github/workflows/release-notes.yml b/.github/workflows/release-notes.yml index 185c03fc57..82ec459ddb 100644 --- a/.github/workflows/release-notes.yml +++ b/.github/workflows/release-notes.yml @@ -24,7 +24,14 @@ name: Generate Release Notes on: - workflow_run: + # `workflow_run` is required here, not incidental: claude-code-action rejects + # the `release` event outright (see the note above), and this needs to run + # after the tag workflow completes. + # + # The risk this audit flags is a privileged workflow checking out an + # event-supplied ref. This one deliberately does not — it checks out the + # default branch, for the reasons set out on the checkout step below. + workflow_run: # zizmor: ignore[dangerous-triggers] workflows: ["Create Release Tag"] types: [completed] workflow_dispatch: