Problem
Pinning actions to SHAs (see #361) removes one CI attack surface, but it does not address vulnerabilities inside the workflow definitions themselves.
The workflows in this repository contain a few well-known GitHub Actions anti-patterns that an attacker could abuse:
- Template injection: GitHub
${{ ... }} expressions are expanded before the shell runs, so any expression interpolated directly into a run: block is substituted as raw text into the script. Values that an attacker can influence (matrix entries, step outputs, cargo-dist install commands, anything derived from a pull request) can therefore break out of the intended command and execute arbitrary shell with access to repository secrets and the GITHUB_TOKEN.
- Credential persistence:
actions/checkout writes the GITHUB_TOKEN into .git/config by default (persist-credentials: true). Every later step - including any third-party action - can read that token and reuse it. This is called an ArtiPACKED Vulnerability.
- Excessive permissions: the release workflow grants
contents: write at the top level, so every job runs with write access even though only a couple of jobs actually need it.
- Unpinned container images: a job pulls a container image from a dynamic matrix, which cannot be expressed as a static SHA pin and needs an explicit, documented exception.
cargo-chef produces the DockerHub image and the released binaries that downstream build pipelines depend on. A compromise of these workflows would let an attacker tamper with those build artifacts. This supply-chain risk needs to be ruled out by security-aware users before adopting cargo-chef.
Why static analysis (zizmor) fixes this
zizmor is a static analysis tool for GitHub Actions workflows. It detects template injection, credential persistence, over-broad permissions, unpinned images, and related findings, and many of them can be auto-corrected with zizmor --fix.
The fixes follow GitHub's own hardening guidance:
- The template-injection fixes use the recommended pattern of passing the expression through an intermediate environment variable instead of interpolating it into the script body. This is the section
zizmor --fix partly automated.
- The permission tightening follows "Restricting permissions for tokens", defaulting the workflow to
contents: read and granting contents: write only to the jobs that publish.
Proposed change
- Run
zizmor as a dedicated CI job so new workflow changes are checked automatically.
- Apply
zizmor --fix and the matching manual fixes:
- move
${{ ... }} expressions out of run: blocks and into env: variables that are referenced as quoted shell variables,
- set
persist-credentials: false on every actions/checkout,
- default the release workflow to
contents: read and escalate to contents: write per job,
- document the one unavoidable
unpinned-images finding with an inline zizmor: ignore and a justification.
References
Problem
Pinning actions to SHAs (see #361) removes one CI attack surface, but it does not address vulnerabilities inside the workflow definitions themselves.
The workflows in this repository contain a few well-known GitHub Actions anti-patterns that an attacker could abuse:
${{ ... }}expressions are expanded before the shell runs, so any expression interpolated directly into arun:block is substituted as raw text into the script. Values that an attacker can influence (matrix entries, step outputs,cargo-distinstall commands, anything derived from a pull request) can therefore break out of the intended command and execute arbitrary shell with access to repository secrets and theGITHUB_TOKEN.actions/checkoutwrites theGITHUB_TOKENinto.git/configby default (persist-credentials: true). Every later step - including any third-party action - can read that token and reuse it. This is called an ArtiPACKED Vulnerability.contents: writeat the top level, so every job runs with write access even though only a couple of jobs actually need it.cargo-chefproduces the DockerHub image and the released binaries that downstream build pipelines depend on. A compromise of these workflows would let an attacker tamper with those build artifacts. This supply-chain risk needs to be ruled out by security-aware users before adoptingcargo-chef.Why static analysis (zizmor) fixes this
zizmoris a static analysis tool for GitHub Actions workflows. It detects template injection, credential persistence, over-broad permissions, unpinned images, and related findings, and many of them can be auto-corrected withzizmor --fix.The fixes follow GitHub's own hardening guidance:
zizmor --fixpartly automated.contents: readand grantingcontents: writeonly to the jobs that publish.Proposed change
zizmoras a dedicated CI job so new workflow changes are checked automatically.zizmor --fixand the matching manual fixes:${{ ... }}expressions out ofrun:blocks and intoenv:variables that are referenced as quoted shell variables,persist-credentials: falseon everyactions/checkout,contents: readand escalate tocontents: writeper job,unpinned-imagesfinding with an inlinezizmor: ignoreand a justification.References
zizmorcore/zizmor-action