Release provenance and verification (JOE-1860 / JOE-1882 / JOE-1919)¶
Aurum release assets ship with byte digests, formal SBOMs, a structured provenance record, and a required cosign keyless signature bundle over SHA256SUMS (JOE-1882).
Honest residual (F-006 / JOE-1919 / JOE-2230)¶
| Claim | Status |
|---|---|
GitHub Release digests + cosign keyless over SHA256SUMS | Required |
PROVENANCE.json full 40-hex source_commit + exact expect match | Required |
| GitHub Actions SLSA build provenance attestations for Tier A CLI + native SDK archives | Required on release (JOE-2230) |
| Full multi-party SLSA L3 / hermetic rebuild of every dependency | Not claimed |
| crates.io crate tarballs in the same cosign/attestation evidence set | Not claimed |
| Bit-for-bit dual-builder equality for all Tier A binaries | Not claimed where variance is documented |
Operators must not infer crates.io package provenance or SLSA L3 from GitHub Release evidence alone.
Artifacts in a GitHub Release¶
| File | Role |
|---|---|
aurum-macos-arm64, aurum-linux-x86_64, aurum-windows-x86_64.exe | Tier A CLI binaries |
SHA256SUMS | Digests of all release files (including SBOMs + provenance) |
SHA256SUMS.bundle | Required cosign keyless signature bundle over SHA256SUMS |
aurum.cdx.json | CycloneDX 1.5 SBOM (required) |
aurum.spdx.json | SPDX 2.3 lite SBOM (required) |
aurum-sbom-inventory.json / .md | Human-oriented dependency inventory |
SBOM_MANIFEST.json | SHA-256 of formal SBOM files |
PROVENANCE.json | Structured build provenance (tag, commit, workflow, per-asset digests) |
PROVENANCE.txt | Human-readable summary of the same |
Verify a downloaded release (fail-closed)¶
# After downloading all assets into ./release-assets
export AURUM_EXPECT_TAG=v0.0.20
export AURUM_EXPECT_COMMIT=<full git sha of the tag>
# Cosign identity for the release workflow + tag (see table below)
export AURUM_REQUIRE_COSIGN=1
export AURUM_COSIGN_CERTIFICATE_OIDC_ISSUER='https://token.actions.githubusercontent.com'
export AURUM_COSIGN_CERTIFICATE_IDENTITY="https://github.com/joe-broadhead/aurum/.github/workflows/release.yml@refs/tags/${AURUM_EXPECT_TAG}"
# Or accept any release tag from this workflow:
# export AURUM_COSIGN_CERTIFICATE_IDENTITY_REGEXP='https://github.com/joe-broadhead/aurum/\.github/workflows/release\.yml@refs/tags/v[0-9]+\.[0-9]+\.[0-9]+'
./scripts/verify_release_assets.sh ./release-assets
What the script checks:
- Every line in
SHA256SUMSmatches on-disk bytes. - Formal SBOMs parse and contain required schema fields + non-empty package lists.
- When
PROVENANCE.jsonis present, tag/commit match env expectations and listed asset digests match files. - When
AURUM_REQUIRE_COSIGN=1(or a bundle is present with identity env),cosign verify-blobvalidatesSHA256SUMS.bundleagainst the OIDC identity.
Install cosign: https://docs.sigstore.dev/cosign/system_config/installation/
Production identity (current)¶
| Field | Value |
|---|---|
| OIDC issuer | https://token.actions.githubusercontent.com |
| Certificate identity (tag push trigger) | …/release.yml@refs/tags/<tag> |
Certificate identity (workflow_dispatch / Tag Release helper) | …/release.yml@refs/heads/master |
| Signed artifact | SHA256SUMS (covers all other assets via digests) |
| Bundle file | SHA256SUMS.bundle |
OIDC subject is the workflow trigger ref, not the git commit checked out for build. Tag Release creates the tag with GITHUB_TOKEN (which does not re-trigger workflows) and then workflow_dispatches release.yml from master, so those releases verify under the master identity. Pure push of vX.Y.Z signs under the tag identity. Release notes for each GitHub Release print the exact string.
Rotation and revocation¶
- Rotation: Keyless signing uses short-lived GitHub OIDC tokens; there is no long-lived release private key to rotate. Changing the signing workflow path or repository name produces a new certificate identity — update this table and release notes, and verify with the new identity string.
- Revocation / compromise response: If a workflow or token is suspected compromised: revoke GitHub Actions secrets, lock down workflow permissions, publish a superseding tag with a clean run, and instruct users to distrust the prior tag's assets. Fulcio/Rekor transparency logs retain historical signatures for audit.
- Offline dry-runs: Local
generate_provenance.shruns do not produce a cosign bundle. SetAURUM_REQUIRE_COSIGN=0(default) for local asset checks.
Generating provenance locally¶
./scripts/generate_sbom.sh dist/sbom
mkdir -p dist/release-assets
cp dist/sbom/* dist/release-assets/
# copy binaries into dist/release-assets, then:
./scripts/generate_provenance.sh dist/release-assets v0.0.20
# rebuild SHA256SUMS after provenance is written (see release.yml)
# cosign sign-blob is performed only in GitHub Actions OIDC context
Trust boundaries¶
- Checksums prove byte equality with the published set — not who published them.
- PROVENANCE.json binds the asset set to a git tag/commit and CI run id when produced by
release.yml. - cosign keyless binds the checksum file to a GitHub OIDC identity for the release workflow at that tag. Always prefer
AURUM_REQUIRE_COSIGN=1for production download verification. - GitHub SLSA attestations (JOE-2230) bind individual CLI/SDK subjects to the workflow that built them. Verify with the GitHub UI or:
Related¶
- release-gate.md — gates before tag
- reproducibility.md — two-builder variance
- platform-support.md — Tier A/B/C platforms
- security.md — security process