Attesting builds with SLSA provenance in CI
Generate an SBOM and signed SLSA provenance for every build, attach them with cosign, and prove exactly where an artifact came from when auditors ask.
After log4shell the question every team could not answer fast was simply: where do we run this library? An SBOM (software bill of materials) inventories every component in an artifact; SLSA provenance is a signed statement of how that artifact was built. Together they turn incident response from grepping Dockerfiles into querying a catalog — and they give admission controllers something verifiable to enforce before a pod schedules.
You will generate a CycloneDX SBOM with Syft, gate on CVEs with Grype, attach the SBOM and build provenance as Cosign attestations using CI OIDC (no long-lived signing key in settings), and verify attestations at deploy time. GitLab and GitHub both support the same toolchain — the full chain from builder trust to cluster policy is in Software supply chain security.
Sign with the CI identity your cloud already trusts. Keyless Cosign binds the signature to the workflow that produced the image.
Generate the SBOM in CI
Run Syft against the built image tag — not only the Dockerfile — so OS packages, language deps, and binaries inside layers all appear. Store the SBOM as a pipeline artifact and attach it to the registry record. Scan the SBOM with Grype before push so a known-critical CVE blocks promotion instead of surfacing in production.
sbom:stage: testimage: anchore/syft:latestscript:- syft "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" -o cyclonedx-json > sbom.json- grype sbom:sbom.json --fail-on highartifacts:paths: [sbom.json]
Attach signed provenance and SBOM
Cosign can sign the image digest and attach attestations — separate signatures that carry predicates like CycloneDX JSON or SLSA provenance v1. Keyless mode uses Fulcio to bind the signature to your CI OIDC identity; verify with policy that checks issuer, repository, and workflow ref.
# after docker push — identity from CI OIDCcosign sign --yes "$IMAGE"cosign attest --yes \--predicate sbom.json \--type cyclonedx \"$IMAGE"cosign attest --yes \--predicate provenance.json \--type slsaprovenance \"$IMAGE"
cosign verify "$IMAGE"Verified OK — issuer matches github.com/acme/repocosign verify-attestation --type cyclonedx "$IMAGE"SBOM attestation verifiedreject deploy if either check failsArchive SBOMs for the next CVE
Keep one SBOM per immutable digest, not just per semver tag — tags can move. When the next critical CVE drops, search your SBOM archive for the affected package version across every image you have ever shipped — minutes instead of a week of repo archaeology. Retention policy should match compliance requirements; SBOMs are evidence, not debug noise. Store them beside the digest they describe so auditors can correlate signature, provenance, and inventory without chasing pipeline IDs.
Where this goes next
Attestations become powerful when Kyverno, Gatekeeper, or registry policy rejects images missing SLSA provenance or failing vulnerability thresholds on the attached SBOM. Wire Syft, Grype, and Cosign into one reusable workflow template so every repo inherits the same bar. Software supply chain security covers builders, signing, and admission verification hands-on.
Go deeper in a courseSoftware supply chain securitySBOMs, SLSA provenance, Cosign signing, and admission verification.View course