diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 043e2c6..f258cb8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -92,8 +92,12 @@ jobs: ( cd "publish/$rid" && zip -qr "../../artifacts/lakespeak-${{ steps.version.outputs.version }}-$rid.zip" . ) done + # Only over what actually reaches the release. Running this across the whole build directory + # put the .nupkg and .snupkg files in the list, and those go to NuGet rather than to the + # release - so `sha256sum -c SHA256SUMS.txt` failed on four of seven entries for anyone who + # downloaded the release and followed SECURITY.md. Shipped that way in 0.1.0. - name: Checksums - run: cd artifacts && sha256sum * > SHA256SUMS.txt && cat SHA256SUMS.txt + run: cd artifacts && sha256sum *.zip > SHA256SUMS.txt && cat SHA256SUMS.txt # An SBOM is the vendor list an adopter's SOC 2 vendor-risk review asks # for. Generated from the restored graph, not hand-maintained. @@ -103,10 +107,15 @@ jobs: export PATH="$PATH:$HOME/.dotnet/tools" dotnet CycloneDX LakeSpeak.slnx -o artifacts --json --filename sbom.json + # The zips are attested as well as the packages. Attesting only the .nupkg files left the + # three downloadable binaries unattested, so `gh attestation verify` on a downloaded release + # binary failed - which is precisely the command SECURITY.md tells an adopter to run. - uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 id: attest with: - subject-path: 'artifacts/*.nupkg' + subject-path: | + artifacts/*.nupkg + artifacts/*.zip # The attestation is reachable through GitHub's Attestations API, but the bundle also has to # land on the release itself: tooling that verifies a downloaded artifact offline has no API diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fa0e2a..a26d762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,24 @@ Notable changes, newest first. This project follows [semantic versioning](https: the caveat that `0.x` minor versions may break the API — that is what `0.x` means, and it is stated here rather than left to be discovered. +## Unreleased + +### Fixed + +- **Release binaries are now attested.** The provenance attestation covered only the `.nupkg` + files, so `gh attestation verify` on a downloaded release binary failed — the exact command + `SECURITY.md` tells an adopter to run. The zips are now attestation subjects too. +- **`SHA256SUMS.txt` now lists only what is actually on the release.** It was generated across the + whole build directory, so it included the four `.nupkg`/`.snupkg` files that go to NuGet rather + than to the release; `sha256sum -c` therefore failed on four of seven entries for anyone who + downloaded 0.1.0. + + Both were found by verifying the published 0.1.0 release rather than the build output. The + verification instructions had been checked against a rehearsal artifacts directory, which + contains the packages — so both commands passed there and failed in reality. `SECURITY.md` now + states what applies to 0.1.0 and what changes from 0.1.1, including the + `sha256sum -c --ignore-missing` form that does work on 0.1.0. + ## 0.1.0 — 2026-08-06 Results come back whole, the documentation's own claims are under test, and the one image that was diff --git a/SECURITY.md b/SECURITY.md index c8a20b7..19a0291 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -94,13 +94,16 @@ Checking it takes one command and needs only the [GitHub CLI](https://cli.github.com): ```bash -gh attestation verify lakespeak-0.1.0-linux-x64.zip --repo ivanvyd/LakeSpeak.NET +gh attestation verify LakeSpeak.Cli.0.1.0.nupkg --repo ivanvyd/LakeSpeak.NET ``` -The same works on a package: +> **Applies from 0.1.1.** In `0.1.0` the attestation covers only the two `.nupkg` files, so running +> the same command against a downloaded release binary fails. That was a packaging mistake, not a +> tampered file: the binaries were built by the same workflow run, and their digests are in that +> release's `SHA256SUMS.txt`. From 0.1.1 the release binaries are attested too: ```bash -gh attestation verify LakeSpeak.Cli.0.1.0.nupkg --repo ivanvyd/LakeSpeak.NET +gh attestation verify lakespeak-0.1.1-linux-x64.zip --repo ivanvyd/LakeSpeak.NET ``` A passing check tells you the file was built by `.github/workflows/release.yml` in this @@ -116,12 +119,18 @@ started by someone holding only the GitHub account. You can check any release ta git -c gpg.ssh.allowedSignersFile=.github/allowed_signers verify-tag v0.1.0 ``` -To check the binaries against their published digests instead: +To check the binaries against their published digests instead, from the directory you downloaded +them into: ```bash sha256sum -c SHA256SUMS.txt ``` +> **Also applies from 0.1.1.** `0.1.0`'s `SHA256SUMS.txt` additionally lists the four `.nupkg` and +> `.snupkg` files, which are published to NuGet rather than attached to the release — so that +> command reports four missing files there. The three entries for the release binaries are correct +> and can be checked individually with `sha256sum -c --ignore-missing SHA256SUMS.txt`. + `sbom.json` on each release is a CycloneDX bill of materials, which is usually what a security review asks for before any of the above.