Why sign images
Registries or transport can be compromised, and tags can be overwritten. A signature binds an image (by digest) to the identity of the person or pipeline that built it, so the deploy side can check: "this image was built by example-org's pipeline from the myapp repo and has not been altered".
Sigstore and cosign
Sigstore is an OpenSSF project made of:
| Component | Role |
|---|---|
| cosign | CLI to sign and verify images, blobs and attestations |
| Fulcio | A CA issuing short-lived certificates based on OIDC identity |
| Rekor | A public transparency log recording every signature |
Signing with a key pair
cosign generate-key-pair # creates cosign.key (password-protected) and cosign.pub
cosign sign --key cosign.key registry.example.com/myapp@sha256:EXAMPLE
cosign verify --key cosign.pub registry.example.com/myapp@sha256:EXAMPLE
The private key can live in a KMS (--key awskms://..., azurekms://...) instead of a file.
Keyless: no keys to manage
In CI with OIDC (GitHub Actions, GitLab), cosign takes the workflow's identity token, Fulcio issues a certificate valid for minutes, and the signature is recorded in Rekor. There is no long-lived private key to leak.
cosign sign registry.example.com/myapp@sha256:EXAMPLE
cosign verify registry.example.com/myapp@sha256:EXAMPLE \
--certificate-identity-regexp '^https://github.com/example-org/myapp/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
Keyless verification must state the expected identity and issuer; otherwise a signature by anyone is accepted.
sequenceDiagram participant CI as CI workflow participant F as Fulcio participant R as Rekor participant REG as Registry CI->>F: workflow OIDC token F-->>CI: short-lived certificate CI->>REG: push signature next to the image CI->>R: record in the transparency log
Attestations
Beyond signatures, cosign attaches signed attestations: an SBOM, scan results, SLSA provenance.
cosign attest --predicate sbom.cdx.json --type cyclonedx registry.example.com/myapp@sha256:EXAMPLE
Enforcing at deploy time
Signing without checking is pointless. In Kubernetes, Kyverno (verifyImages) or the Sigstore policy-controller reject Pods using unsigned images or images signed by an unexpected identity.
Traps: signing a tag instead of a digest; keyless verification without an identity restriction; keeping cosign.key in the repo; signing while the cluster never checks.