Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 13 additions & 4 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.

Expand Down
Loading