.github: scope actions: write to merge-queue self-cancel jobs (#21132) - #22677
Merged
AskAlexSharov merged 1 commit intoJul 23, 2026
Merged
Conversation
These CI test workflows self-cancel the CI Gate run on first merge-queue failure via `gh run cancel`, which needs actions: write. Add explicit least-privilege permissions instead of relying on the broad default token: - Single-job workflows (check-large-files, lint, reproducible-build, test-all-erigon, test-bench, sonar): top-level contents: read + actions: write. - Multi-job workflows (test-all-erigon-race, test-eest-spec, test-integration-caplin): top-level contents: read, with actions: write scoped to only the jobs that run the cancel step. sonar also reads the Actions API (gh api runs/artifacts, download-artifact, covered by actions: write) and gets pull-requests: read for SonarCloud PR analysis context. Part of the #21132 excessive-permissions cleanup.
AskAlexSharov
approved these changes
Jul 23, 2026
AskAlexSharov
deleted the
feature/lystopad/zizmor-excessive-perms-actions-21132
branch
July 23, 2026 03:01
Sahil-4555
pushed a commit
to Sahil-4555/erigon
that referenced
this pull request
Jul 23, 2026
…ws (erigontech#21132) (erigontech#22687) Part of the zizmor `excessive-permissions` cleanup (erigontech#21132). Follow-up to erigontech#22662 and erigontech#22677. ## What Adds explicit least-privilege `permissions:` blocks to 5 workflows that were running on the broad default token: | Workflow | Scope | Why | |---|---|---| | `ci-cd-main-branch-docker-images` | `contents: read` | DockerHub only — auth via DockerHub secrets, no GitHub token used | | `qa-txpool-performance-test` | `contents: read` | DockerHub **pull** only | | `test-hive` | `contents: read` + `actions: write` | merge-queue self-cancel via `gh run cancel` | | `test-hive-eest` | `contents: read` + `actions: write` | merge-queue self-cancel via `gh run cancel` | | `test-kurtosis-assertoor` | top-level `contents: read`; `actions: write` on `assertoor_test` only | only that job runs `gh run cancel` | ## Notes - DockerHub login/push uses DockerHub secrets, not the GitHub token, so it needs **no** GitHub permission. - `test-kurtosis-assertoor` builds the erigon image with `load: true` (no registry push), so **no `packages: write`** is required; `actions: write` is scoped to the single job that self-cancels rather than the workflow level (which would trip "overly broad"). ## Verification - zizmor `excessive-permissions`: **12 → 3** for these files (the remaining 3 are `ci-gate`/`test-fuzz`, handled next). - `actionlint` clean w.r.t. this change (only pre-existing shellcheck notes remain); `make lint` = 0 issues. ## Rollout note The audit stays `disable: true` in `.github/zizmor.yml` until the series finishes; the final PR flips it on so the gate enforces it. > Note: `docker-tags.yml` — originally slated for this batch — is being **removed** in a separate PR instead of scoped, as it is a dead 2023 experiment (0 runs ever, references a non-existent `make release-dry-run` target, triggers only on `y*.*.*` test tags).
pull Bot
pushed a commit
to Dustin4444/erigon
that referenced
this pull request
Jul 23, 2026
…cleanup (erigontech#22694) **Final PR of the zizmor `excessive-permissions` cleanup — closes erigontech#21132** (with erigontech#22688). Follows erigontech#22662, erigontech#22677, erigontech#22687 (and the dead-workflow removal erigontech#22688). ## What 1. **`test-fuzz.yml`** — move `issues: write` from the workflow level to the `notify` job (the only job that opens/updates the `nightly-fuzz` tracking issue). The fuzz matrix job keeps `contents: read`. 2. **`.github/zizmor.yml`** — replace the blanket `excessive-permissions: disable: true` with a per-file `ignore` of just `ci-gate.yml`, and **enable the audit** for every other workflow. ## Why `ci-gate` is ignored rather than scoped `ci-gate` orchestrates the reusable test leaves. Per GitHub's rules, **a called workflow's `GITHUB_TOKEN` permissions are capped by the caller** — so ci-gate's workflow-level grants are not "for itself", they're the ceiling every leaf inherits: - **`actions: write`** is the cap that lets all ~12 self-cancelling leaves (scoped in erigontech#22677/erigontech#22687) actually run `gh run cancel` on merge-queue failure. Dropping it silently breaks fast-cancel and the gate stalls. - **`pull-requests: write`** drives the gate's own `dequeuePullRequest` GraphQL mutation (GitHub doesn't auto-remove UNMERGEABLE queue entries), and is also the cap for sonar's inherited `pull-requests: read`. Neither can be scoped to a single job without adding per-job `permissions` caps to every leaf-call job on the merge gate — high risk for no real privilege gain. The in-file comment documents this, mirrored into the ignore justification. ## Verification - Full repo, real `.github/zizmor.yml`, **with `docker-tags.yml` removed (as erigontech#22688 does)**: `zizmor` → **exit 0, "No findings to report"** (17 ignored, 299 suppressed). - On this branch alone (docker-tags still present until erigontech#22688 merges): exit 13 — one *medium* `docker-tags` finding that erigontech#22688 removes; the gate passes regardless (< 14). - `actionlint` clean; `make lint` = 0 issues. ## Merge order Pairs with **erigontech#22688** (docker-tags removal). Either order is safe (the gate passes both ways); once both land, `excessive-permissions` reports zero findings and **erigontech#21132 can close**. The only remaining zizmor exceptions repo-wide are the deliberate policy ones (`unpinned-uses`, `concurrency-limits`) and the justified per-file ignores (`cache-poisoning`, `secrets-inherit`, and now `excessive-permissions` → ci-gate).
Sahil-4555
pushed a commit
to Sahil-4555/erigon
that referenced
this pull request
Jul 24, 2026
…usable-workflow perms) (erigontech#22714) ## Regression fix — `startup_failure` on main since erigontech#22677 The `excessive-permissions` cleanup (erigontech#22677, erigontech#22687) gave the reusable test leaves explicit permissions (`actions: write` for their merge-queue `gh run cancel`, `pull-requests: read` for sonar). GitHub validates a **called** workflow's declared permissions against the **caller's** grant *at startup* and rejects the whole run if the caller grants less. Callers that only granted `contents: read` therefore began failing to start: | Caller | Calls | Broke at | Effect | |---|---|---|---| | `cache-warming` | lint, sonar, test-bench, test-all-erigon, … | erigontech#22677 | `startup_failure`, **33 checks** dropped | | `sonar-branch-scan` | sonar | erigontech#22677 | `startup_failure`, **1 check** dropped | | `cache-warming-kurtosis-cl-images` | test-kurtosis-assertoor | erigontech#22687 | `startup_failure` | Both cache-warming and sonar-branch-scan went `success` → `startup_failure` exactly at commit `6f7557ebec` (erigontech#22677) and have failed on **every main commit since** — silently dropping ~34 checks per commit (this is the "134 → 99" drop visible in main's commit history). `ci-gate` was unaffected because it already grants `actions: write` + `pull-requests: write`; `cache-warming-kurtosis-gloas-images` is unaffected because its leaf (`test-kurtosis-gloas`) was never modified and still declares only `contents: read` — a clean control confirming the mechanism. ## Fix Grant each broken caller the union of its leaves' declared permissions: - `cache-warming` → `contents: read`, `actions: write`, `pull-requests: read` - `sonar-branch-scan` → `contents: read`, `actions: write`, `pull-requests: read` - `cache-warming-kurtosis-cl-images` → `contents: read`, `actions: write` These callers are orchestrators that must grant the leaf permission cap workflow-wide (exactly like `ci-gate`), so they're added to the `excessive-permissions` ignore list with a generalized justification. ## Verification - `zizmor` (real `.github/zizmor.yml`, audit enabled): **exit 0, "No findings to report."** - `actionlint` clean on the diff (the pre-existing `concurrency.queue` note is unrelated). - `make lint` = 0 issues. - Post-merge confirmation: the push-triggered `Cache Warming` and `SonarCloud Branch Scan` runs on main should return to `success` (from `startup_failure`). ## Note / lesson Root cause was mine: when adding the leaves' `permissions:` in erigontech#22677/erigontech#22687 I didn't account for GitHub's caller-must-grant rule for reusable workflows, so non-ci-gate callers broke. This restores them without weakening the least-privilege scoping. --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the zizmor
excessive-permissionscleanup (#21132). Follow-up to #22662.What
These CI test workflows self-cancel the CI Gate run on the first merge-queue failure via
gh run cancel ${{ github.run_id }}(so the gate doesn't stall on still-running siblings). That call needsactions: write. Instead of relying on the repo's broad default token grant, each now declares explicit least-privilege permissions.Single-job — top-level block:
check-large-files,lint,reproducible-build,test-all-erigon,test-bench→contents: read+actions: writesonar→contents: read+actions: write+pull-requests: readMulti-job — top-level
contents: read, withactions: writeadded only to the jobs that run the cancel step:test-all-erigon-race→load-matrix,tests-linuxtest-eest-spec→eest-spec-tests,eest-shard-coveragetest-integration-caplin→tests,tests-windowsNotes on the non-obvious scopes
sonaralso reads the Actions API (gh api .../runs,.../artifacts, anddownload-artifactfor merge-queue coverage reuse) — covered byactions: write.pull-requests: readpreserves SonarCloud's PR-analysis context (the scan step runs only outside the merge queue).actions: writeis deliberately not placed at the workflow level (zizmor flags that as "overly broad") — it's scoped to the specific cancel jobs.Verification
excessive-permissions: 28 → 12 — all 9 files here resolved, no new "overly broad at the workflow level" findings introduced.actionlintclean w.r.t. this change;make lint= 0 issues.Rollout note
The audit stays
disable: truein.github/zizmor.ymluntil the series finishes (docker/packages group + theci-gate/test-fuzzper-job rescoping remain); the final PR flips it on so the gate enforces it.