Articles / Image Signing and Provenance with Sigstore and cosign
Containers · Supply Chain

Image Signing and Provenance with Sigstore and cosign

Image scanning answers 'is this artifact vulnerable?' Signing and provenance answer a different, prior question: 'is this the artifact my pipeline actually built, or something an attacker slipped into the registry?' Between the two lives most of software supply-chain security. A vulnerability scan on a tampered image is a careful audit of the wrong thing.

Container image tags are mutable and, on their own, prove nothing about origin. Anyone with push access — legitimately or through a compromised credential — can overwrite app:latest with a backdoored build, and by default nothing downstream will notice. Signing binds an image's immutable content digest to a cryptographic signature, so a consumer can verify both that it came from a trusted signer and that its bytes are unchanged.

What Sigstore changed

pushpullverifiedCI buildOIDC workload identitycosign signkeyless, logged in RekorRegistryimage + signatureAdmissionverify signer identityPod runsPush access →overwrite tag with abackdoorUnenforced policy →unsigned image runs
Signing and admission verification bind an image to the pipeline that built it.

Traditional signing foundered on key management: developers had to generate, distribute, and — hardest of all — protect long-lived private keys, and a leaked key silently undermined everything. Sigstore, a CNCF project, reframes the problem around 'keyless' signing. Its cosign tool obtains a short-lived certificate from the Fulcio CA, bound to an OIDC identity (a CI workflow's token, say, or a developer's SSO identity), signs with an ephemeral key, and records the signature in Rekor, a public append-only transparency log. There is no long-lived secret to steal, and the transparency log makes signatures auditable after the fact.

Why it matters: Keyless signing removes the private key that was the whole vulnerability. The signer is a verifiable identity — 'the release workflow in this repo' — not a secret that could be exfiltrated and reused.

Provenance and SLSA: signing the build, not just the artifact

A signature proves who signed an image; it does not by itself prove how the image was built. Provenance closes that gap. A build provenance attestation is a signed statement — typically in the in-toto format — describing what source commit was built, by which builder, with which parameters. Verify it and you know the image genuinely came from commit abc123 built by your trusted CI, not from a laptop with registry credentials.

SLSA (Supply-chain Levels for Software Artifacts) frames this as a ladder. Lower levels ask for scripted, provenance-emitting builds; higher levels demand hardened, non-falsifiable build platforms where even a build engineer cannot forge provenance. You do not need the top rung to benefit — generating and verifying provenance at all defeats the most common tampering.

  • Sign every image at build time. Have CI run cosign sign against the pushed digest using its workload identity, not a stored key.
  • Generate build provenance. Emit an in-toto/SLSA attestation binding the image to its source commit and builder, and sign it alongside the image.
  • Verify at admission, not just in docs. A policy that no one enforces is a suggestion. Use an admission controller to reject unsigned or unverified images before they run.
  • Pin trust to identities. Verify the signer's OIDC identity and issuer (e.g. this specific repo's release workflow), not merely that some valid signature exists.
  • Attach the SBOM as a signed attestation too. A signed bill of materials you can trust beats an unsigned one you have to take on faith.
Keyless sign in CI, verify against a trusted identity# in the release workflow (identity comes from the CI OIDC token)
cosign sign registry/app@sha256:9f3c1...

# at admission / deploy
cosign verify \
  --certificate-identity-regexp 'https://github.com/acme/app/.github/workflows/release.yml@.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  registry/app@sha256:9f3c1...

Where it fits

Signing and provenance are the trust layer beneath everything else in this series. Minimal images and diligent scanning reduce what can go wrong inside a build you control; signatures and provenance ensure the thing running in production is that build. Enforced at admission with a controller like Kyverno or Sigstore's policy-controller, they turn 'we trust our registry' into a checkable property.

But verification only protects the clusters and pipelines you have wired it into. An unmanaged deployment that pulls whatever tag it is pointed at, with no signature check, re-opens the door you shut everywhere else — which is why knowing every place your organisation runs containers comes before trusting any of them.

Test for it — in practice
  • Take a production image digest and check whether any signature exists for it — an unsigned image tells you nothing about who built it.
  • Ask whether anything actually rejects an unsigned image at deploy time; a signing policy no admission controller enforces is documentation, not a control.

Confirming one image is signed is a spot check; verifying provenance is enforced everywhere it should be is what our assessment runs for you.

Keep reading
The Container Supply Chain: From Dockerfile to Registry to Runtime