Uh oh!
There was an error while loading. Please reload this page.
ci: attest build provenance for the release artifacts - #39
Conversation
The release path produced a notarized macOS zip, a Windows zip and a sha256 in the Homebrew cask, none of it tied back to the run or commit that built it. A checksum proves the file didn't change in transit; anyone who can write to the release (or the tap) can publish a consistent zip-plus-checksum pair. Notarization proves Apple saw the binary and that it carries our Developer ID — it says nothing about which source tree it was built from. Adds actions/attest-build-provenance (pinned to a SHA, per #4) to both release jobs, publishing a signed SLSA statement that binds the artifact digest to the repo, workflow and commit: gh attestation verify Blurt-macOS.zip --repo lightware-dev/blurt Scoped to release tags — attestation is about what we publish, and a PR build isn't. The version-less Blurt-<platform>.zip copies need no separate statement: they're byte-identical and attestations are keyed by digest, not filename. Per-job permissions widen to id-token: write + attestations: write. This matters more on the Windows side, where releases are unsigned (#9), so the attestation is currently the only cryptographic link between a download and this repository. It is not a substitute for signing, and neither defends against repo write access: an attacker who can push a tag gets CI to attest their payload. What both defend is a release asset replaced *without* a code push. Also fixes a README claim while adding the verification instructions: the Windows section said "grab the latest signed build", which has never been true — exactly the misreading #9 is about, and it was in the docs as well as the workflow. Closes#24
z33b0t
commented
Jul 29, 2026
@z33b0t ready to merge. All 8 checks green, including the macOS and Windows builds (this PR touches both workflows). Merge after #37 — both change the release jobs, and #37 reworks the publish step these sit next to. Two things worth reading before you merge:
Not executed anywhere — the step only fires on a |
z33b0t
commented
Jul 29, 2026
@z33b0t Green and ready, but I can't merge this one — my Either merge it yourself, or grant the scope and I'll finish: (Oddly, #30 and #37 modified workflows and merged fine before this started refusing — so the restriction isn't applying consistently. Worth knowing in case you see it again.) |
Adds
actions/attest-build-provenance(pinned to0f67c3f/ v4.1.1, per #4) to both release jobs, with per-jobid-token: write+attestations: write.Scoped to release tags only — a PR build isn't published, so there's nothing to attest. The version-less
Blurt-<platform>.zipcopies don't need their own statement: they're byte-identical and attestations are keyed by digest, not filename.One caveat I want on the record
This attests the bytes this run built. On a re-run where the release already carries an earlier attempt's asset, the upload step deliberately leaves the published file untouched (no
--clobber, per #5) — and a macOS rebuild is never byte-identical, since codesign embeds a fresh timestamp and stapling a newly-issued ticket. The attestation would then cover a digest that isn't the one published, andgh attestation verifyon the downloaded file would fail.It's the same trap the cask-bump step already documents and guards against. I've noted it in a comment rather than engineered around it, because the fix (attest the published bytes by re-downloading) costs a download on every release to handle a case that means "delete the asset and re-run clean" anyway. Flagging it so it's a known edge rather than a surprise.
README correction included
While adding the verification instructions I hit a claim that's plainly false:
Windows releases have never been signed (#9). That's the same misreading #9 is about — it wasn't only the workflow implying it, the docs said it outright. Now corrected to state builds are unsigned, SmartScreen will warn, and the attestation is the cryptographic link that does exist.
Verification
YAML parses and step ordering is confirmed; the action SHA resolves to the
v4.1.1tag. Not executed — the step only runs on av*tag, so the first real exercise is the next release. Worth checking the run produces the attestation and thatgh attestation verifypasses against the published asset before trusting it.Closes#24