Sigstore and Cosign: Verifying Container Images Before They Run
Signing without managing keys, and proving an image is what it claims

A container tag is a lie you’ve agreed to believe. nginx:latest today and
nginx:latest next week can be entirely different bytes, and a tag tells you
nothing about who built the image or whether it’s been swapped underneath you.
The whole modern supply-chain panic — compromised build pipelines, typosquatted
images, dependency confusion — comes down to that one weak link: we run images we
can’t actually verify. Sigstore, and its CLI cosign, is the most practical fix
I’ve adopted, mostly because it finally killed the part of signing that everyone
hated: key management.
1 Keyless signing, and why it’s the headline feature
Traditional code signing means generating a long-lived private key, guarding it forever, rotating it, and panicking if it leaks. Almost nobody does this well. Sigstore’s clever move is keyless signing: instead of a key you hold, you authenticate to an OIDC identity provider (your Google, GitHub, or corporate account), and Sigstore’s certificate authority, Fulcio, issues a short-lived certificate — valid for roughly ten minutes — bound to that identity. You sign with it, then it expires. There’s no key to steal because there’s no persistent key.
The signature, certificate, and a record of the event are published to Rekor, a public append-only transparency log. That log is the trust anchor: anyone can later prove the signature existed and hasn’t been backdated.
# sign an image keyless — a browser opens for OIDC auth
$ cosign sign registry.example.net/api@sha256:5d9f...
Generating ephemeral keys...
Retrieving signed certificate from Fulcio...
tlog entry created with index: 84213907Note I signed the digest, not the tag. Always sign and verify by digest — signing a tag is signing a moving target.
2 Verifying before you trust
Verification is where the value lands. You assert who you expect to have signed it and which OIDC issuer vouched for that identity:
$ cosign verify \
--certificate-identity '[email protected]' \
--certificate-oidc-issuer 'https://accounts.google.com' \
registry.example.net/api@sha256:5d9f... | jq '.[0].optional'
Verification for registry.example.net/api@sha256:5d9f... --
The following checks were performed:
- The cosign claims were validated
- Existence of the entry in the transparency log was verified
- The signing certificate identity matches the expected oneThose two --certificate-* flags are not optional in spirit. If you skip them,
cosign will happily verify that somebody signed the image — which is nearly
useless. The security comes from pinning the expected identity and issuer.
3 Going further: SBOMs and attestations
A signature says “this is the image I built”. An attestation says something about the image — most usefully an SBOM (software bill of materials) listing every package inside, so you can answer “is the new critical CVE in any image I’m running?” without guessing.
# attach an SBOM as a signed attestation
$ cosign attest --type cyclonedx \
--predicate sbom.cdx.json \
registry.example.net/api@sha256:5d9f...
# later, verify and pull the SBOM back out
$ cosign verify-attestation --type cyclonedx \
--certificate-identity '[email protected]' \
--certificate-oidc-issuer 'https://accounts.google.com' \
registry.example.net/api@sha256:5d9f... \
| jq -r '.payload' | base64 -d | jq '.predicate.components | length'
142Now a signature, an SBOM, and a transparency-log entry all travel with the image. That’s a real provenance trail rather than a hopeful tag.
4 Enforcing it where it counts: admission control
Verifying by hand is good discipline; enforcing it in the cluster is what actually stops a bad image running. A policy controller — the Sigstore policy controller, or Kyverno’s image-verification rules — intercepts every pod and rejects images that don’t carry a valid signature from an approved identity.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
validationFailureAction: Enforce
rules:
- name: verify-api-images
match:
any:
- resources:
kinds: [Pod]
verifyImages:
- imageReferences:
- "registry.example.net/*"
attestors:
- entries:
- keyless:
issuer: "https://accounts.google.com"
subject: "[email protected]"With Enforce, an unsigned or wrongly-signed image never schedules. That’s the
line between “we sign things, mostly” and “unsigned images cannot run here”.
5 The verdict
Worth it? If you pull images from anywhere you don’t fully control — and that’s nearly everyone — keyless signing removes the single biggest excuse for not signing, and verification by pinned identity genuinely raises the bar against supply-chain tampering. The honest caveats: keyless ties you to an OIDC provider and the public Rekor log, which some air-gapped or privacy-sensitive setups won’t accept (you can self-host both, at real operational cost). And signatures verify provenance, not safety — a signed image can still be vulnerable. This is for teams running their own registries and clusters who want to stop trusting tags on faith. For a single hobby box pulling official images, it’s overkill; verifying the official signatures by hand is plenty.




