Skip to content

actions: audit workflows with zizmor, and fix what it found - #123

Merged
katbyte merged 1 commit into
mainfrom
kt/zizmar-it
Sep 18, 2026
Merged

katbyte merged 1 commit into
mainfrom
kt/zizmar-it

Conversation

@katbyte

@katbyte katbyte commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Adds zizmor, a security scanner for GitHub Actions workflows, and fixes everything it flagged.

Why

Workflows run with real power — they can publish releases, write to the repo and read secrets. A mistake in one is a way for someone to borrow that power. actionlint already checks our workflows for syntax and shell mistakes, but it does not look for this.

What it found

Checkouts keeping a password they did not need. Checking out the code leaves a credential on disk for the rest of the job. None of these jobs push anything, so it is now thrown away as soon as the code is fetched.

   - uses: actions/checkout@...
+     with:
+       persist-credentials: false

A build cache the release job could be tricked into trusting. The release job restored a cache that ordinary PR builds can write to. A poisoned entry would end up inside a published binary. The release now builds without the cache.

   - uses: actions/setup-go@...
     with:
+      cache: false

Dependency updates landing the moment they are published. Dependabot opened PRs as soon as a new version appeared, which is exactly when a compromised release is most likely to still be undetected. Updates now wait a week.

   - package-ecosystem: gomod
+    cooldown:
+      default-days: 7

The one thing left as it is. The release uses SLSA's builder to sign what we publish, and that has to be referenced by tag rather than a commit hash — it checks its own reference at runtime. Marked so the scanner stops asking, with the existing comment explaining why.

-  uses: slsa-framework/slsa-github-generator/...@v2.1.0
+  uses: slsa-framework/slsa-github-generator/...@v2.1.0  # zizmor: ignore[unpinned-uses]

How it runs

make zizmor locally, and a workflow security audit check on PRs that touch workflows and on pushes to main — the same shape as the existing typos and actionlint checks. The binary is pinned in the makefile alongside shellcheck and typos.

Adds zizmor alongside actionlint: actionlint covers syntax, expressions
and shell, zizmor covers credential persistence, cache poisoning and
unpinned actions.

Drops the checkout credential nothing was using, stops the release job
restoring a cache that PR builds can write to, and gives dependabot a
week of cooldown. The SLSA builder stays on a tag, which it requires.
contents: write # upload multiple.intoto.jsonl to the release
# the slsa builder must be referenced by tag, not commit hash; it verifies its own ref at runtime
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 # zizmor: ignore[unpinned-uses]
@katbyte
katbyte merged commit 1c909ba into main Sep 18, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants