Skip to content

CI(zizmor): Add per-repo zizmor security audit workflow#289

Open
ModeSevenIndustrialSolutions wants to merge 4 commits into
lfit:mainfrom
modeseven-lfit:feat/zizmor-workflow
Open

CI(zizmor): Add per-repo zizmor security audit workflow#289
ModeSevenIndustrialSolutions wants to merge 4 commits into
lfit:mainfrom
modeseven-lfit:feat/zizmor-workflow

Conversation

@ModeSevenIndustrialSolutions
Copy link
Copy Markdown
Contributor

@ModeSevenIndustrialSolutions ModeSevenIndustrialSolutions commented May 12, 2026

Summary

Adds the zizmor SARIF audit workflow developed in
lfreleng-actions/.github
to dependamerge so PRs and pushes get static security
analysis of every workflow file in this repository — without
relying on the org-wide required-workflow ruleset having been
deployed at the org level.

The workflow file itself is functionally identical to upstream;
only the leading documentation block has been adapted to reflect
the per-repo deployment context (and to fix references to docs
that live upstream rather than in this repo).

What this PR adds

Path Purpose
.github/workflows/zizmor.yaml The audit workflow (per-repo deployment of the upstream workflow)
.github/dependabot/zizmor-requirements.txt Local pin of the zizmor version (zizmor==1.24.1) consumed by the workflow at runtime
.github/dependabot.yml (edit) New pip ecosystem entry targeting /.github/dependabot/ so Dependabot keeps the pin file current via PRs

The pin file is vendored locally so the effective zizmor version
is reviewed via a PR in this repo and never silently changes
between runs. The upstream-fetch fallback in the workflow is
retained for drop-in compatibility with repositories that have
not vendored the pin, but is unreachable in this repo by design.

How I verified it runs cleanly here

The workflow is designed to be deployed at the org level as a
"required workflow" against many repositories that don't
contain the file or any companion scripts, so it is already
fully self-contained:

Concern Status in this repo
harden-runner egress policy audit mode — no CONNECTION_WHITELIST needed → fork PRs work out of the box
Companion Python parser Embedded as base64 inside the workflow file, decoded at runtime; source of truth lives upstream at lfreleng-actions/.github/.github/scripts/zizmor_summary.py
Zizmor version pin Vendored locally at .github/dependabot/zizmor-requirements.txt; Dependabot's pip ecosystem keeps it current
Required secrets / vars Only secrets.GITHUB_TOKEN (always available)
Permissions on PR runs contents: read only — the elevated security-events: write job is gated to default-branch pushes, so fork PRs never request it
Action SHA pins All actions pinned to commit SHAs (matches this repo's # Do NOT use tag object SHAs rule)
push: trigger Scoped to branches: [main] so feature-branch and tag pushes do not create no-op runs

Behaviour

  • PR runs: zizmor runs in SARIF mode (always exits 0), the
    embedded Python parser writes a markdown summary to the run
    page, and findings appear as inline annotations on the
    changed lines. Advisory only — never blocks merges.
  • Default-branch pushes: same as above, plus the SARIF
    artifact is uploaded to GitHub code scanning where alerts
    are tracked.

Validation

All checks clean:

  • actionlint
  • yamllint ✅ (the upstream's slightly stricter
    comments: min-spaces-from-content: 1, level: error rule is
    already satisfied, so dependamerge's looser config is
    guaranteed to pass)
  • All applicable pre-commit hooks pass on the changed files
    (yamllint, actionlint, GitHub Actions Workflow Linter,
    Validate GitHub Workflows, Check GitHub Workflows set
    timeout-minutes, reuse, codespell, …)

Notes

This comment was marked as outdated.

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/zizmor.yaml Outdated
Adds the zizmor SARIF audit workflow developed in
lfreleng-actions/.github to dependamerge so PRs and pushes
get static analysis of every workflow file in this repository
without relying on the org-wide required-workflow ruleset
having been deployed.

Self-contained behaviour (no further modifications needed):

* harden-runner runs in audit-only mode, so the workflow does
  not depend on CONNECTION_WHITELIST being exposed and runs
  cleanly on fork PRs.
* The Python summary parser is embedded as base64 in the
  workflow file itself; the upstream source script in
  lfreleng-actions/.github remains the source of truth for
  regenerating the embedded copy.
* The zizmor version pin is vendored locally at
  .github/dependabot/zizmor-requirements.txt and maintained
  by Dependabot's pip ecosystem (added in dependabot.yml), so
  the pin is always reviewed via a PR in this repo and never
  silently changes between runs.  Deployment mode is detected
  from GITHUB_WORKFLOW_REF so a PR that deletes both files
  from its head commit still fails closed.
* Only secrets.GITHUB_TOKEN is required (always available).
* SARIF upload to GitHub code scanning is gated to
  default-branch pushes, so PR runs never request the
  elevated security-events: write permission.  PR runs are
  advisory only and write a markdown summary to the run page
  plus inline annotations on the changed lines.
* The push trigger is scoped to the default branch (main) so
  feature-branch and tag pushes do not create no-op runs.

Address Copilot review feedback:

* Vendor zizmor pin file locally and add pip ecosystem entry
  to dependabot.yml so the version is reviewed and tracked
  in-repo, removing the supply-chain dependency on the
  unpinned upstream main branch fetch in normal operation.
* Reword pin comment block to reflect per-repo context.
* Reword embedded-parser maintenance comment to point at the
  upstream source of truth in lfreleng-actions/.github.
* Scope the push trigger to the main branch instead of all
  refs.
* Remove the stale reference to a README section that lived
  in the upstream .github org profile and does not exist in
  this repository.
* Restructure the workflow header comment so it leads with
  the per-repo deployment context (which is what readers of
  this file primarily need to understand) and only mentions
  the upstream org-wide-ruleset deployment mode as background.
* Detect per-repo deployment from GITHUB_WORKFLOW_REF rather
  than workspace file presence.  A PR head cannot tamper with
  GITHUB_WORKFLOW_REF, so a PR that deletes both the workflow
  file and the pin file still fails closed instead of silently
  pivoting onto the mutable upstream main branch copy of the
  pin.
* Correct the inaccurate comment on the download-artifact step
  that claimed the action would extract under a subdirectory
  named after the artifact without an explicit path.  v4+
  extracts a named single-artifact download to the workspace
  root by default; the explicit `path: '.'` is kept as a
  belt-and-braces hint of where the file lands.

Validation:

* actionlint clean.
* yamllint clean.
* All applicable pre-commit hooks pass on the changed files
  (yamllint, actionlint, GitHub Actions Workflow Linter,
  Validate GitHub Workflows, Check GitHub Workflows set
  timeout-minutes, reuse, codespell, ...).

Co-authored-by: Claude <claude@anthropic.com>
Signed-off-by: Matthew Watkins <mwatkins@linuxfoundation.org>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Add a 7-day cooldown window to each Dependabot updates entry
so that new releases must age for a week before Dependabot
opens a PR against them.  This narrows the window in which a
freshly-published-but-yet-to-be-discovered malicious release
can land in this repository, and was flagged by the new zizmor
dependabot-cooldown audit (workflow added in the previous
commit).

The 7-day default applies uniformly to:

* github-actions
* uv
* pip (the zizmor pin file)

Co-authored-by: Claude <claude@anthropic.com>
Signed-off-by: Matthew Watkins <mwatkins@linuxfoundation.org>
The autolabeler workflow uses pull_request_target so it can
label PRs raised from forks.  The new zizmor audit (added in
this branch) flags pull_request_target generically under the
dangerous-triggers rule, but the conditions the rule warns
about cannot occur in this workflow:

* The workflow performs no checkout of PR code (no
  actions/checkout step).
* The workflow body is loaded from the base branch
  (pull_request_target semantics), not from the PR head.
* The only step is release-drafter/autolabeler, pinned to a
  commit SHA, which is a pure GitHub-API consumer and never
  executes PR-provided content.
* Permissions are scoped to pull-requests: write and
  contents: read; no secrets are exposed to the job.
* The runner is hardened with an egress block.

Suppress the audit on the pull_request_target trigger with an
inline zizmor: ignore[dangerous-triggers] directive and add a
header comment documenting the rationale, so future readers
can see at a glance why the trigger is safe here and why the
generic warning has been silenced.

Co-authored-by: Claude <claude@anthropic.com>
Signed-off-by: Matthew Watkins <mwatkins@linuxfoundation.org>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread .github/workflows/zizmor.yaml
Comment thread .github/workflows/autolabeler.yaml
Two hardening fixes surfaced by Copilot's review of the
preceding three commits on this branch:

* zizmor.yaml: strictly validate the extracted zizmor pin
  before passing it to `uvx --from`.  Without this check, a
  PR that edits .github/dependabot/zizmor-requirements.txt
  could feed uvx an arbitrary pip requirement spec (VCS/URL
  refs, --index-url and other options, environment markers,
  multiple lines, or additional packages), resulting in
  untrusted code execution on the runner under the base
  repository's GITHUB_TOKEN.  The check now accepts exactly
  one line matching ^zizmor==<version>$ where <version> is a
  conservative subset of PEP 440, and rejects anything else.
* autolabeler.yaml: reword the safety rationale's permissions
  bullet to clarify that the default GITHUB_TOKEN is still
  passed to the job (with the scoped pull-requests: write and
  contents: read permissions) and only the absence of
  additional repository secrets is being claimed.  The
  previous wording "no secrets are exposed" understated the
  privileges and could mislead future readers.

Co-authored-by: Claude <claude@anthropic.com>
Signed-off-by: Matthew Watkins <mwatkins@linuxfoundation.org>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants