From 002aa2f541e4b725717feed652be677716fee024 Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Sun, 27 Sep 2026 22:25:22 +0300 Subject: [PATCH 1/5] Do not leave the checkout's token in .git/config zizmor's artipacked audit flagged 6 actions/checkout steps that keep the GITHUB_TOKEN in the repository's .git/config for the rest of the job, where every later step can read it, and an artifact that uploads the checkout would carry it. No job here pushes with git: the draft release attaches to a tag that is already pushed (skipTag), and the Central upload, the draft release, the dependency graph and the CodeQL results go through APIs with their own tokens. Every checkout now sets persist-credentials: false, as the one in zizmor.yml already did. --- .github/workflows/ci.yml | 2 ++ .github/workflows/codeql-analysis.yml | 2 ++ .github/workflows/dependency-submission.yml | 2 ++ .github/workflows/release.yml | 2 ++ .github/workflows/sha-pinning-check.yml | 2 ++ 5 files changed, 10 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a054e6..6fbdb12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Install JDK 21 uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6599573..c72c1ec 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,6 +31,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Set up JDK 21 uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 diff --git a/.github/workflows/dependency-submission.yml b/.github/workflows/dependency-submission.yml index 4b4c6bc..73f2e85 100644 --- a/.github/workflows/dependency-submission.yml +++ b/.github/workflows/dependency-submission.yml @@ -12,6 +12,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Set up JDK 21 uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3410113..4e213e6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,6 +31,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 + persist-credentials: false - name: Install JDK 21 uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 @@ -91,6 +92,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 + persist-credentials: false - name: Install JDK 21 uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 diff --git a/.github/workflows/sha-pinning-check.yml b/.github/workflows/sha-pinning-check.yml index 16cfdd7..aac1aa0 100644 --- a/.github/workflows/sha-pinning-check.yml +++ b/.github/workflows/sha-pinning-check.yml @@ -11,5 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: zgosalvez/github-actions-ensure-sha-pinned-actions@62574f011e0d1967d555a862bd28a7abba8684fe # v5.0.9 From 93c984fa071324eb2a1cad927786ed3fe7670406 Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Sun, 27 Sep 2026 22:25:37 +0300 Subject: [PATCH 2/5] Give the two workflows without a permissions block the least they need sha-pinning-check.yml and update-pr-branch.yml ran with the default GITHUB_TOKEN permissions, which zizmor (excessive-permissions) and CodeQL (actions/missing-workflow-permissions) both flagged. The pin check only checks the repository out and reads its workflow files, so it gets contents: read. update-pr-branch reads and updates the pull requests with BOT_PAT, the only token the action reads, so the workflow's own token gets no permissions at all. --- .github/workflows/sha-pinning-check.yml | 3 +++ .github/workflows/update-pr-branch.yml | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/sha-pinning-check.yml b/.github/workflows/sha-pinning-check.yml index aac1aa0..181c6e7 100644 --- a/.github/workflows/sha-pinning-check.yml +++ b/.github/workflows/sha-pinning-check.yml @@ -6,6 +6,9 @@ on: push: branches: [ 'main' ] +permissions: + contents: read + jobs: pin-check: runs-on: ubuntu-latest diff --git a/.github/workflows/update-pr-branch.yml b/.github/workflows/update-pr-branch.yml index d0ef7a7..eff6c9c 100644 --- a/.github/workflows/update-pr-branch.yml +++ b/.github/workflows/update-pr-branch.yml @@ -7,6 +7,10 @@ on: # Run every hour to catch stuck PRs - cron: '0 * * * *' +# The action reads and updates the pull requests with BOT_PAT alone, so the workflow's own token needs +# no permissions. +permissions: {} + jobs: update: runs-on: ubuntu-latest From c0e64dff0cbef65a912cfdf1146f0a16d9d792c1 Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Sun, 27 Sep 2026 22:25:51 +0300 Subject: [PATCH 3/5] Check who opened the pull request before auto-merging it The Dependabot auto-merge job ran when github.actor was dependabot[bot]. zizmor (bot-conditions) flags that as spoofable: the actor is whoever caused the event, so a run Dependabot triggers on a pull request someone else opened passes the check, and the job then approves the pull request and enables auto-merge. The job now checks github.event.pull_request.user.login, the author of the pull request, which is the condition GitHub's own documentation for Dependabot auto-merge uses. dependabot/fetch-metadata still checks the author and that the commits are Dependabot's before anything is approved. --- .github/workflows/dependabot-automerge.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dependabot-automerge.yml b/.github/workflows/dependabot-automerge.yml index 7aab910..bca4dec 100644 --- a/.github/workflows/dependabot-automerge.yml +++ b/.github/workflows/dependabot-automerge.yml @@ -9,7 +9,9 @@ permissions: jobs: dependabot: runs-on: ubuntu-latest - if: github.actor == 'dependabot[bot]' + # Who opened the pull request, not who triggered this run: github.actor is whoever caused the event, + # and a run that Dependabot triggers on someone else's pull request would pass an actor check. + if: github.event.pull_request.user.login == 'dependabot[bot]' steps: - name: Fetch Dependabot metadata id: metadata From dee008411e027d1a42b77d91c31008d4955b84db Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Sun, 27 Sep 2026 22:26:02 +0300 Subject: [PATCH 4/5] Name the CodeQL action release the pin points to The CodeQL workflow pins github/codeql-action to 1c5b6756, commented as v4. v4 is a moving tag and now points to 2892aa5e (v4.38.2), so zizmor (ref-version-mismatch) reports that the comment does not match the pin. 1c5b6756 is v4.38.1, and the comments now say so. The pinned commit stays the same; Dependabot updates it, and the comment with it. --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c72c1ec..c6c09c0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -41,7 +41,7 @@ jobs: java-version: '21' - name: Initialize CodeQL - uses: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4 + uses: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -51,6 +51,6 @@ jobs: run: mvn --no-transfer-progress -B clean test-compile - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4 + uses: github/codeql-action/analyze@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1 with: category: "/language:${{matrix.language}}" From a16560231f909bb55ca0f94c6f87e05ceadcb6cf Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Sun, 27 Sep 2026 22:26:15 +0300 Subject: [PATCH 5/5] Let Dependabot propose a release only once it is a week old zizmor (dependabot-cooldown) flagged both update entries in dependabot.yml: without a cooldown, Dependabot waits only its implicit three days before it proposes a new version of an action or a Maven dependency. A compromised or broken release is usually pulled within days, and the auto-merge workflow approves minor and patch updates on its own, so both entries now wait seven days. The cooldown applies to version updates only; security updates are not delayed. --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7b31302..d4ff3fc 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,13 +1,19 @@ version: 2 +# A release is proposed only once it is a week old: a compromised or broken release is usually pulled +# within days. The cooldown holds back version updates only; security updates still come at once. updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" target-branch: "main" + cooldown: + default-days: 7 - package-ecosystem: "maven" directory: "/" schedule: interval: "weekly" target-branch: "main" + cooldown: + default-days: 7