fix: keep zizmor auditing when a uses: target is unreadable - #10
Merged
Conversation
zizmor 1.28.0's online audits resolve every repository a workflow references with `uses:`. When one is private to the token in use, zizmor does not skip that audit — it aborts the run with "fatal: no audit was performed" and writes a 0-byte SARIF. GITHUB_TOKEN is scoped to the repository being scanned, so any consumer whose build calls a private reusable workflow gets no audit at all. That is the default state for such a repo, not an edge case: it went red on the first consumer to reference one. Extract the invocation into bin/run-zizmor.sh, which runs the online audits and retries with --no-online-audits only on that specific lookup failure. Offline audits still run and still report — the retry on the reproduction below returns a real unpinned-uses finding rather than an empty file. The retry is deliberately narrow. Retrying on any nonzero exit would turn an unparseable workflow or a missing binary into a green job, which is indistinguishable from "audited and found nothing" — bin/test-run-zizmor.sh pins that an unrelated failure stays red and is not retried. Adds the optional gh-api-token secret for consumers that want the online audits kept: supply a token that can read every referenced repository. Defaults to GITHUB_TOKEN, so nothing changes for repos referencing only public actions. Verified against real zizmor 1.28.0 on a workflow referencing an unreadable repository: before, exit 1 and a 0-byte SARIF; after, exit 0, a 6.4 KB SARIF and one finding. With a token that can read every reference, the online audits run untouched — exit 0, no warning, 23 findings. 15 new tests; detect (17) and report-sarif (22) still pass; actionlint and shellcheck clean.
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.
The bug
zizmor 1.28.0's online audits (
ref-confusion, and the commit lookup insideunpinned-uses) resolve every repository a workflow references withuses:. When one of them is private to the token in use, zizmor does not skip that audit — it aborts the whole run:The SARIF comes out 0 bytes.
GITHUB_TOKENis scoped to the repository being scanned, so this is the default state for any consumer whose build calls a private reusable workflow — not an edge case.Scope: every consumer of this workflow references a private first-party repository (
cleancoders/infrastructure, pluscleancoders/epic-poker-e2ein two of them), so all of them have been aborting and uploading empty SARIFs. The zizmor job has therefore been reporting nothing fleet-wide, and that went unnoticed because the job is advisory. This repo's ownself-testis the exception — it callssecurity.ymlby local path, so it has no unreadable reference and its online audits work, which is why CI here stayed green while consumers produced nothing.Worth noting the failure mode: the job is red and the artifact is empty, so there is nothing to triage. The advisory
continue-on-errorkeeps it from blocking builds, which is also what keeps it easy to ignore indefinitely.The fix
Extract the invocation into
bin/run-zizmor.sh, following thereport-sarif.shprecedent so the decision is testable rather than inline shell:--no-online-auditsonly on that specific lookup failure. Offline audits still run and still report — the retry on the reproduction below returns a realunpinned-usesfinding instead of an empty file.That last point is the one I'd most want reviewed. Retrying on any failure would turn an unparseable workflow or a missing binary into a green job — indistinguishable from "audited and found nothing", which is the failure mode this repo exists to prevent.
bin/test-run-zizmor.shpins it: an unrelated failure stays red and is not retried.Also adds an optional
gh-api-tokensecret for consumers that want the online audits kept — supply a token that can read every referenced repository. It defaults toGITHUB_TOKEN, so nothing changes for repos referencing only public actions.Verification
Against real zizmor 1.28.0, on a fixture workflow referencing an unreadable repository:
unpinned-uses)With a token that can read every reference, the online audits run untouched: exit 0, no warning, 23 findings — so the fix does not quietly disable them where they work.
bin/test-run-zizmor.sh— 15 new tests, wired intoself-test.ymlbin/test-detect.sh(17) andbin/test-report-sarif.sh(22) still passactionlintandshellcheckclean on the new filesNote on
v1v1moved twice in one afternoon while I was tracking this down, which made a local reproduction stale mid-investigation. Not part of this change, but it makes consumer-side debugging harder than it needs to be.🤖 Generated with Claude Code