Today — zizmor 1.29.0, the exact version ci.yml:157 pins, at the same persona and the same auto-discovered .github/zizmor.yml:
$ zizmor --persona=pedantic .github/workflows/ action/action.yml
No findings to report. Good job! (10 ignored, 3 suppressed)
exit=0
$ zizmor --persona=pedantic action/track.example.yml
error[excessive-permissions]: overly broad permissions
--> action/track.example.yml:18:3
18 | issues: write
| ^^^^^^^^^^^^^ issues: write is overly broad at the workflow level
error[unpinned-uses]: unpinned action reference
--> action/track.example.yml:25:15
25 | uses: vyncint/mossaic/action@v0.6.3
error[unpinned-uses]: unpinned action reference
--> action/track.example.yml:81:15
81 | uses: dawidd6/action-send-mail@v18
help[undocumented-permissions] --> action/track.example.yml:18:3
info[anonymous-definition] --> action/track.example.yml:21:3 (job `track:`)
help[concurrency-limits] --> action/track.example.yml:8:1
11 findings (5 suppressed, 2 unsafe fixes): 1 informational, 2 low, 0 medium, 3 high
exit=14
$ sed -n '1,18p' action/track.example.yml
# Copy this to .github/workflows/track.yml in a public repository of your own,
…
permissions:
contents: read
# Only needed by the issue-comment step below.
issues: write
Why it is worth fixing — ci.yml's own comment gives the reason action.yml was added to the audit: "The composite action is audited too: it pulls actions of its own, and it is the piece other people run in their repositories." track.example.yml is that piece more directly — its first line tells you to copy it into a public repository of your own. It is not under .github/workflows/, so neither the CI glob nor GitHub itself ever parses it, and .github/zizmor.yml holds no exemption for it: an oversight rather than a stated boundary, and an invisible one, because CI is green and the file that fails the gate is the only one the gate is not pointed at.
Whoever follows the instructions inherits workflow-level issues: write for every step — including the one running dawidd6/action-send-mail@v18, a mutable tag on somebody else's repository — in a workflow designed to run unattended on a daily cron. SECURITY.md advertises "every GitHub Action pinned to a full commit SHA" as posture; the shipped template pins none. This is not a vulnerability in mossaic itself, so the public tracker is the right place for it under SECURITY.md's own split.
The vyncint/mossaic/action@v0.6.3 hit is not one of the real ones: pinning the action by tag is documented project style (action/README.md does it twice, and version: is the release knob), so it wants a config exemption rather than a fix.
Fix — add action/track.example.yml to the zizmor invocation in ci.yml, then fix what it reports:
- move
issues: write down to the Comment on the tracking issue step — line 17 of the file already says it is only needed there — leaving contents: read at the workflow level;
- SHA-pin
dawidd6/action-send-mail, with a # v18 comment, the way every action in .github/workflows/ is written;
- give the job a
name: and add a concurrency: block; both are one line and both are things the project's own workflows already do;
- add a scoped
unpinned-uses exemption for vyncint/mossaic/action to .github/zizmor.yml, with the rationale already written in action/README.md.
action/README.md has no permissions: block of its own, so only the SHA-pin change applies to the copy of the block there — but it is the copy most people will actually paste, so it has to match.
Done when — pipx run zizmor==1.29.0 --persona=pedantic .github/workflows/ action/action.yml action/track.example.yml exits 0; the example workflow grants no write scope above the step that needs it; the third-party action is SHA-pinned; and the block in action/README.md matches the file.
Today — zizmor 1.29.0, the exact version ci.yml:157 pins, at the same persona and the same auto-discovered
.github/zizmor.yml:Why it is worth fixing — ci.yml's own comment gives the reason action.yml was added to the audit: "The composite action is audited too: it pulls actions of its own, and it is the piece other people run in their repositories." track.example.yml is that piece more directly — its first line tells you to copy it into a public repository of your own. It is not under
.github/workflows/, so neither the CI glob nor GitHub itself ever parses it, and.github/zizmor.ymlholds no exemption for it: an oversight rather than a stated boundary, and an invisible one, because CI is green and the file that fails the gate is the only one the gate is not pointed at.Whoever follows the instructions inherits workflow-level
issues: writefor every step — including the one runningdawidd6/action-send-mail@v18, a mutable tag on somebody else's repository — in a workflow designed to run unattended on a daily cron. SECURITY.md advertises "every GitHub Action pinned to a full commit SHA" as posture; the shipped template pins none. This is not a vulnerability in mossaic itself, so the public tracker is the right place for it under SECURITY.md's own split.The
vyncint/mossaic/action@v0.6.3hit is not one of the real ones: pinning the action by tag is documented project style (action/README.md does it twice, andversion:is the release knob), so it wants a config exemption rather than a fix.Fix — add
action/track.example.ymlto the zizmor invocation in ci.yml, then fix what it reports:issues: writedown to theComment on the tracking issuestep — line 17 of the file already says it is only needed there — leavingcontents: readat the workflow level;dawidd6/action-send-mail, with a# v18comment, the way every action in.github/workflows/is written;name:and add aconcurrency:block; both are one line and both are things the project's own workflows already do;unpinned-usesexemption forvyncint/mossaic/actionto.github/zizmor.yml, with the rationale already written in action/README.md.action/README.md has no
permissions:block of its own, so only the SHA-pin change applies to the copy of the block there — but it is the copy most people will actually paste, so it has to match.Done when —
pipx run zizmor==1.29.0 --persona=pedantic .github/workflows/ action/action.yml action/track.example.ymlexits 0; the example workflow grants no write scope above the step that needs it; the third-party action is SHA-pinned; and the block in action/README.md matches the file.