Skip to content
Latchkey

Signing Images and Provenance (cosign, attestations)

A signature answers a simple question -- did this exact image really come from our pipeline, and has it been altered?

Scanning tells you what is in an image; signing tells you who built it and that it has not changed. Together they form the backbone of software supply chain security. This lesson introduces keyless signing with cosign and build provenance attestations.

Why sign images

Without a signature, a deployment system trusts a tag or digest on faith. A signature cryptographically binds the image digest to an identity, so a verifier can reject any image that was not produced and signed by your pipeline.

Keyless signing with cosign

cosign can sign keylessly using your workflow OIDC identity, so there is no private key to store or leak.

.github/workflows/sign.yml
permissions:
  id-token: write
  packages: write
steps:
  - uses: sigstore/cosign-installer@v3
  - run: cosign sign --yes ghcr.io/acme/myapp@${DIGEST}
    env:
      COSIGN_EXPERIMENTAL: "1"

Attach provenance

Provenance (a SLSA-style attestation) records how, where, and from what source the image was built. buildx can generate it during the build with --provenance=true, and consumers can require it before deploying.

Verify before deploy

On the deploy side, verify the signature and the identity that produced it. A mismatch blocks the deploy.

Terminal
cosign verify \
  --certificate-identity-regexp "https://github.com/acme/.*" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/acme/myapp@${DIGEST}

Key takeaways

  • Signing binds an image digest to an identity so consumers can detect tampering.
  • Keyless cosign signing uses workflow OIDC identity -- no private key to store.
  • Provenance attestations record how and where an image was built; verify both before deploy.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →