Add PR check to enforce SHA-pinned GitHub Actions - #2771
Merged
Conversation
Runs zizmor against .github/workflows (and .github/actions, if present) on every PR that touches them, and fails the check if any action is referenced by a mutable tag/branch instead of a full commit SHA. Follows up on the one-time SHA-pinning remediation to prevent regressions. Exceptions can be added inline with a '# zizmor: ignore[unpinned-uses]' comment, demonstrated on the notification-pr-bot@main reference which intentionally tracks main.
🧪 Review environmenthttps://2j7gzkouvrrtt24xsbsbjmckjq0cbhly.lambda-url.ca-central-1.on.aws/ |
Keeps the exception self-documenting per zizmor's own convention (# zizmor: ignore[rule] <reason>), rather than relying on a separate comment line above that could get edited or moved away independently.
…ants Falls back to the concrete feature (or a placeholder) instead of printing null if the location isn't a Local symbolic key.
Passing a nonexistent local path caused zizmor to misinterpret it as a remote owner/repo spec and fail with a GitHub API 404, since most of these repos don't have composite actions under .github/actions.
Copilot's suggested fix used a nonexistent 'given_path' field and lost the finding-level '.desc' by restructuring through .locations[] without capturing it first - verified it actually printed 'unknown location:N: null' against real zizmor output. This version keeps .desc, selects the Primary location, and adds a line number.
ben851
approved these changes
Aug 26, 2026
This was referenced Aug 26, 2026
18 tasks
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.
Description
Follow-up to the GH Actions SHA-pinning remediation: adds a mandatory PR check that automatically fails if a workflow or composite action references a third-party action by a mutable tag/branch instead of a full 40-character commit SHA. Same implementation as cds-snc/notification-manifests#5133.
Why not Renovate or the existing OSSF Scorecard job?
Pinned-Dependenciescheck only runs weekly/on push tomainas a scoring job — it never runs onpull_requestand doesn't fail the build.Neither currently blocks a PR, which is the actual gap this closes.
What this does
.github/workflows/check_pinned_actions.yaml, triggered onpull_request/push:mainwhen.github/workflows/**or.github/actions/**change.zizmorand filters its results down to just theunpinned-usesfinding, so it stays scoped to SHA-pinning only (zizmor's other audits, e.g.template-injection, are a separate concern, out of scope here).# zizmor: ignore[unpinned-uses] <reason>comment skips the check for that line. Demonstrated oncds-snc/notification-pr-bot@mainindocker.yaml, which intentionally tracksmain(already excluded from Renovate via this repo'srenovate.jsonignoreDeps) and can't be hash-pinned without losing that behavior.To make this a real merge gate
Branch protection on
mainneeds "Scan for unpinned actions" added as a required status check (not done in this PR — repo settings, not code).Testing
Ran
zizmorlocally against this repo's.github/workflows: found and fixed the one pre-existingunpinned-usesfinding, confirmed 0 findings remain, and confirmed the CI script correctly fails against a deliberately unpinned test workflow.