Skip to content

ci: sign + attest released images and binary (provenance + SBOM, ADR-15)#18

Merged
wrkode merged 1 commit into
mainfrom
ci/release-attestation
Jun 9, 2026
Merged

ci: sign + attest released images and binary (provenance + SBOM, ADR-15)#18
wrkode merged 1 commit into
mainfrom
ci/release-attestation

Conversation

@wrkode

@wrkode wrkode commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

What

Sign and attest the artifacts the Release workflow publishes (ADR-15) -- the publish-side half of supply-chain principle 5. The Dockerfile already checksum-verifies what it downloads; this covers what we ship.

Per tag, release.yml now:

  • captures each per-minor image digest after push and attaches a keyless SLSA build-provenance attestation + an SPDX SBOM attestation (syft) by digest. The :<tag>/:latest aliases share the digest, so one attestation covers all three tags.
  • attaches provenance + SBOM attestations to the release binary.
  • self-verifies its own attestations (gh attestation verify) before publishing -- a broken signing step fails the release, not a tester.
  • tightens permissions to least privilege per job (top-level contents: read).
  • pins the new signing/SBOM actions to commit SHAs.

GitHub-native attestations (keyless OIDC, no private key); cosign deferred (ghcr lacks the OCI Referrers API). Verification is documented in the release notes, README.md, and docs/testing.md.

Verification

actionlint clean. security-architect reviewed the implementation (CHANGES-REQUIRED -> both fixed): the SPDX predicate-type is the versioned https://spdx.dev/Document/v2.3, and anchore/sbom-action upload-release-assets is disabled. It confirmed push-to-registry succeeds on ghcr, permissions are correctly least-privilege, and the trigger is tag-push-only.

Reviewed statically (a release cannot run without a tag); the live proof is the first tag, where the self-verify step exercises the whole chain end to end. CI + docs only; no production code.

🤖 Generated with Claude Code

Extend design-principle 5 (signature-verified supply chain) to the artifacts
we PUBLISH. The Dockerfile already checksum-verifies binaries it downloads;
this adds publish-side provenance + SBOM so a tester can verify integrity and
origin.

release.yml now, per tag:
- captures each per-minor image digest after push and attaches a keyless SLSA
  build-provenance attestation and an SPDX SBOM attestation (syft) by digest;
  the :<tag>/:latest aliases share that digest, so one attestation covers all.
- attaches provenance + SBOM attestations to the release binary tarball.
- self-verifies its own attestations (gh attestation verify) before publishing,
  so broken signing fails the release rather than reaching a tester.
- tightens permissions to least privilege per job (top-level contents: read;
  images: packages+id-token+attestations; binary: contents+id-token+attestations).
- pins the new signing/SBOM actions to commit SHAs.

GitHub-native attestations (keyless OIDC, no private key); cosign deferred
because ghcr lacks the OCI Referrers API. Verification documented in the
release notes, README, and docs/testing.md.

Security-architect reviewed the implementation: the SPDX predicate-type is the
versioned https://spdx.dev/Document/v2.3 and anchore/sbom-action
upload-release-assets is disabled so the scanner never authors Release assets.
actionlint clean. Live proof is the first tag (the self-verify step).

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: William Rizzo <william.rizzo@gmail.com>
@wrkode
wrkode merged commit 92cbb28 into main Jun 9, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant