@sebastienrousseau/dotfiles
Version:
The Trusted Shell Platform — Universal dotfiles managed by Chezmoi. Features Bash & Zsh for macOS, Linux & WSL. Rust modern tooling & enterprise-grade security.
202 lines (160 loc) • 8.02 kB
Markdown
title: "Verify a Release"
date: 2026-05-17
# Verifying a Release
Every release of the framework ships four independent attestations.
Verify any of them, they're orthogonal and each rules out a
different class of attack.
| Artefact | Format | Tool | Threat covered |
|----------|--------|------|----------------|
| **SBOM** (`dotfiles-sbom.spdx.json`) | SPDX 2.3 JSON | any SBOM viewer | "what's in the release?", full component inventory |
| **Cosign signature** (`.sig` + `.pem`) | sigstore keyless | `cosign verify-blob` | "did our CI actually produce this SBOM?", short-lived Fulcio cert + Rekor transparency-log entry |
| **SLSA provenance** (`.intoto.jsonl`) | in-toto v1 / SLSA L3 | `slsa-verifier` | "what build process produced this?", workflow ID, source ref, builder identity |
| **Unified manifest** (`ALL_SHA256SUMS` + `.sig` + `.pem`) | text + sigstore keyless | `cosign verify-blob` then `sha256sum -c` | "is every other asset on this release the one our CI produced?", one signed line per asset |
All four are attached to every GitHub Release as assets, from v0.2.503 forward.
Releases v0.2.500 through v0.2.502 carry the SBOM bundle only: the unified
manifest landed in v0.2.503 and is forward-only (re-tagging earlier releases
would break consumer pins on existing SHAs).
## TL;DR — verify v0.2.503+ end-to-end
```sh
# 0. Pick the release to verify
TAG=v0.2.503
REPO=sebastienrousseau/dotfiles
# 1. Download every attestation artefact
gh release download "$TAG" --repo "$REPO" \
--pattern dotfiles-sbom.spdx.json \
--pattern dotfiles-sbom.spdx.json.sig \
--pattern dotfiles-sbom.spdx.json.pem \
--pattern dotfiles-sbom.spdx.json.intoto.jsonl \
--pattern ALL_SHA256SUMS \
--pattern ALL_SHA256SUMS.sig \
--pattern ALL_SHA256SUMS.pem
# 2. Verify Cosign signature on the SBOM (binds SBOM to CI workflow identity)
cosign verify-blob \
--certificate dotfiles-sbom.spdx.json.pem \
--signature dotfiles-sbom.spdx.json.sig \
--certificate-identity-regexp "^https://github.com/$REPO/" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
dotfiles-sbom.spdx.json
# 3. Verify SLSA provenance (binds SBOM to exact source tag + builder)
slsa-verifier verify-artifact dotfiles-sbom.spdx.json \
--provenance-path dotfiles-sbom.spdx.json.intoto.jsonl \
--source-uri "github.com/$REPO" \
--source-tag "$TAG"
# 4. Verify the unified manifest, then verify every other asset against it.
# One signed file covers all release artefacts in one shot.
cosign verify-blob \
--certificate ALL_SHA256SUMS.pem \
--signature ALL_SHA256SUMS.sig \
--certificate-identity-regexp "^https://github.com/$REPO/" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ALL_SHA256SUMS
gh release download "$TAG" --repo "$REPO" --dir . # pull every other asset
sha256sum -c ALL_SHA256SUMS # one line per asset
```
All four commands should print "Verified" / "PASSED" / "OK" and
exit 0. If any fails, **the release was tampered with**: open
an issue at <https://github.com/sebastienrousseau/dotfiles/issues>
and do **not** install.
## Tool installation
| Tool | macOS | Linux | Windows |
|------|-------|-------|---------|
| `gh` (GitHub CLI) | `brew install gh` | `apt install gh` / [release page](https://github.com/cli/cli/releases) | `scoop install gh` |
| `cosign` | `brew install cosign` | `curl -sSfL https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o /usr/local/bin/cosign && chmod +x /usr/local/bin/cosign` | `scoop install cosign` |
| `slsa-verifier` | `brew install slsa-verifier` | `go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@latest` | `scoop install slsa-verifier` |
If you don't have Go installed, fetch the pre-built `slsa-verifier`
binary from <https://github.com/slsa-framework/slsa-verifier/releases>
(SHA256-verify per their release notes).
## What each verification actually proves
### `cosign verify-blob` succeeds
- The SBOM was signed by a workflow run **on this repository** (the
`--certificate-identity-regexp` enforces it).
- The signing OIDC token was issued by **GitHub Actions** (the
`--certificate-oidc-issuer` enforces it).
- The signature is recorded in the **Rekor public transparency log**
(cosign queries this automatically) — anyone can audit it.
- The Cosign cert was issued by **Fulcio** (the sigstore CA) and
was valid at the time of signing.
This **does not** prove what the build process did — only that
"the file you have is the file CI produced." For "what did CI do",
see SLSA verification below.
### `slsa-verifier verify-artifact` succeeds
- The SBOM digest matches a provenance statement.
- The provenance was generated by the **SLSA-Generator** running on
**GitHub-hosted runners** for **this exact repository**.
- The build was triggered by the named tag (`--source-tag $TAG`).
- The provenance is anchored in Rekor (immutable, third-party-auditable).
SLSA Level 3 is achieved because: (a) the provenance is generated
by a *trusted, isolated* builder (slsa-github-generator), not by
us; (b) the builder runs with hermetic, non-falsifiable inputs;
(c) the provenance is signed by the builder's own identity, not
ours.
### What none of this proves
The framework's source code is **not formally verified**. SBOM +
SLSA + Cosign protect the *supply chain* (you got what we shipped)
— not the *correctness* (what we shipped does what we claim).
For correctness review:
- Code is open under MIT — read it. Start at `bin/dot`.
- CI runs ~75 checks per PR (shellcheck, shfmt, CodeQL, Semgrep, Codacy, etc.).
- Pre-commit hooks reject typos, unsigned commits, raw secrets.
- See `docs/security/SCORECARD.md` for the OpenSSF score posture.
## In-shell one-liner for ongoing verification
If you intend to install or update from a release tag, add this to
your shell startup (already in `dot_config/shell/*` for users who
run `chezmoi apply`):
```sh
verify-dot-release() {
local tag="${1:-$(gh release view --json tagName --jq .tagName \
--repo sebastienrousseau/dotfiles)}"
local tmp
tmp="$(mktemp -d)"
( cd "$tmp" \
&& gh release download "$tag" --repo sebastienrousseau/dotfiles \
--pattern 'dotfiles-sbom.*' \
&& cosign verify-blob \
--certificate dotfiles-sbom.spdx.json.pem \
--signature dotfiles-sbom.spdx.json.sig \
--certificate-identity-regexp '^https://github.com/sebastienrousseau/dotfiles/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
dotfiles-sbom.spdx.json \
&& slsa-verifier verify-artifact dotfiles-sbom.spdx.json \
--provenance-path dotfiles-sbom.spdx.json.intoto.jsonl \
--source-uri github.com/sebastienrousseau/dotfiles \
--source-tag "$tag"
)
local rc=$?
rm -rf "$tmp"
return $rc
}
```
Usage:
```sh
verify-dot-release # verify latest
verify-dot-release v0.2.502 # verify specific tag
```
## If verification fails
1. **Don't install.** Stop the bootstrap script. `^C` any in-flight
`chezmoi apply`.
2. **Compare assets**. The release page shows file sizes — if
yours don't match what's on
<https://github.com/sebastienrousseau/dotfiles/releases>, you
downloaded from a man-in-the-middle.
3. **Report**: open an issue and email
`security@sebastienrousseau.com` (encrypted to the WKD-published
GPG key — fingerprint
`55AFAD364FD9DB3819E61F0C8D688FAFA9144693`). Acknowledgement
SLA: 72 hours per `.github/SECURITY.md`.
## See also
- `.github/SECURITY.md` — coordinated disclosure policy.
- `docs/security/KEY_ROTATION.md` — disclosure-key rotation procedure.
- `docs/security/SCORECARD.md` — OpenSSF Scorecard posture.
- `docs/operations/HARD_AUDIT_2026.md` Part 7 — the GPG key generation + WKD publication record.
- [Sigstore Cosign docs](https://docs.sigstore.dev/cosign/signing/overview/)
- [SLSA verifier docs](https://github.com/slsa-framework/slsa-verifier)