Within the Supply Chain Security domain of the CKS — roughly 20% of the exam — there are two questions every security engineer eventually has to answer about a container image: what’s inside it, and who put it there and has it changed since? Vulnerability scanning answers the first. Image signing and verification answers the second, and it’s a curriculum bullet in its own right: sign and validate images. This guide goes deep on that bullet using Cosign and the broader Sigstore project, then shows how to turn a signature from a nice-to-have into an enforced gate — a cluster that rejects any image that isn’t signed by a key you trust.
If you want the full sweep of the domain — minimizing base images, scanning with Trivy, static analysis, and the classic ImagePolicyWebhook — start with the CKS Supply Chain Security guide. This article deliberately stays in one lane: signing and verifying image integrity and provenance, and enforcing it at the admission boundary.
Why Signing, Not Just Scanning
Scanning and signing solve different problems, and the exam expects you to know which is which.
- Scanning (for example,
trivy image) inspects the contents of an image and reports known vulnerabilities. It tells you the image has a CRITICAL CVE. It tells you nothing about where the image came from or whether someone tampered with it after it was built. - Signing attaches a cryptographic signature to an image so that anyone can later verify two things: integrity (the image bytes haven’t changed since signing) and provenance (it was signed by a party you trust). A signature says nothing about vulnerabilities — a signed image can still be full of CVEs.
You need both. A robust supply chain scans an image to know it’s clean and verifies a signature to know it’s authentic — and then refuses to run anything that fails either check.
Mental model: scanning is detective (“what’s in here?”); signing plus admission enforcement is preventive (“only trusted, unmodified images may run”). Scanning is the subject of the Trivy section in the supply-chain pillar; this article is the preventive half.
The Sigstore Ecosystem in One Diagram’s Worth of Words
Cosign is the CLI most people touch, but it’s one piece of Sigstore, an open-source project (now under the OpenSSF) that makes signing container images and other artifacts practical. Three components matter conceptually:
| Component | Role |
|---|---|
| Cosign | The tool that signs and verifies container images and artifacts |
| Fulcio | A certificate authority that issues short-lived signing certificates tied to an identity (used in keyless signing) |
| Rekor | A public, tamper-evident transparency log that records signatures so they can be audited later |
Cosign can work in two modes: key-based, where you hold a private key, and keyless, where Fulcio issues a short-lived certificate against an OIDC identity and the signature is recorded in Rekor. Both produce a signature that verifiers can check.
Exam-honesty note: The CKS curriculum bullet is simply sign and validate images, and the exam environment centers on key-based Cosign — generate a key pair, sign, verify, and enforce. Keyless signing, Fulcio, and Rekor are real-world Sigstore context that matters on the job and in interviews, but don’t expect the exam to ask you to stand up a Fulcio CA. Learn key-based signing to exam depth; understand keyless as background. (This mirrors how the field keeps moving faster than the printed objectives — know the tested path cold, and know where the ecosystem is heading.)
Key-Based Signing with Cosign: The Exam Path
The core key-based workflow is short. If you’ve already seen the basic command snippet in the CKS exam topics breakdown, this is the same starting point — generate a key pair, sign, verify — so we’ll move through it quickly and then go past it into attestations and enforcement.
# 1. Generate a key pair (creates cosign.key + cosign.pub)
cosign generate-key-pair
# 2. Sign an image by digest (always prefer digest over tag)
cosign sign --key cosign.key myregistry.io/app@sha256:<digest>
# 3. Verify the signature with the public key
cosign verify --key cosign.pub myregistry.io/app@sha256:<digest>
A few things that separate a pass from a fumble on the exam:
- Sign by digest, not tag. Tags are mutable —
:v1can be repointed to a different image tomorrow, and a signature bound to a tag is meaningless. A digest (@sha256:...) is immutable. Cosign resolves tags to digests under the hood, but reasoning in digests keeps you honest. - The signature lives in the registry. Cosign stores the signature as an additional artifact alongside the image in the same OCI registry (historically under a
.sigtag derived from the digest). You don’t need a separate signature store — your registry already holds it. This is why a registry that supports OCI artifacts is all the infrastructure you need. - Protect the private key.
cosign.keyis password-encrypted on disk, but in a cluster you don’t scatter private keys around. Store signing keys in a KMS or a Kubernetes Secret with encryption at rest — see encrypting Secrets at rest with a KMS. Cosign can also read keys directly from cloud KMS providers via akms://reference so the private key never lands on disk at all.
Signing more than just images: attestations and SBOMs
Cosign can attach and verify attestations — signed statements about an image, such as an SBOM (software bill of materials) or the result of a scan. This is where signing and scanning meet: you can generate an SBOM with your scanner, then sign it as an attestation so downstream verifiers trust it.
# Attach a signed SBOM attestation to the image
cosign attest --key cosign.key --type cyclonedx \
--predicate sbom.json myregistry.io/app@sha256:<digest>
# Verify the attestation later
cosign verify-attestation --key cosign.pub \
--type cyclonedx myregistry.io/app@sha256:<digest>
verify-attestation is the command people forget exists. verify checks that the image is signed; verify-attestation checks a signed claim about the image. Knowing the difference is the kind of detail that shows up in a well-written exam question.
Turning Verification into Enforcement at Admission
Signing an image and verifying it by hand proves nothing about your cluster — someone can still kubectl run an unsigned image. The security win comes from enforcement at the admission boundary: the API server consults an admission webhook that verifies the signature and rejects any pod whose image isn’t signed by a trusted key. This is the preventive control the exam cares about.
There are two modern ways to do this. (The classic ImagePolicyWebhook admission controller is covered in the supply-chain guide; it can gate on registry and policy, but signature verification today is typically done with a policy engine that speaks Sigstore natively.)
Option 1: Kyverno verifyImages
Kyverno has a purpose-built verifyImages rule that verifies Cosign signatures at admission and can even mutate image references to their digest. This is the most commonly cited approach because Kyverno policies are plain YAML — no new language to learn.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
validationFailureAction: Enforce # reject on failure, don't just warn
rules:
- name: verify-app-signature
match:
any:
- resources:
kinds: ["Pod"]
verifyImages:
- imageReferences:
- "myregistry.io/app*"
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
<contents of cosign.pub>
-----END PUBLIC KEY-----
With validationFailureAction: Enforce, any pod that references myregistry.io/app* without a signature that matches this public key is rejected by the API server. Switch it to Audit while you roll out, then flip to Enforce. Kyverno can also verify keyless signatures by matching on identities and issuers instead of keys, and it verifies attestations too.
Option 2: The Sigstore policy-controller
The Sigstore project ships its own admission controller, the policy-controller, configured with a ClusterImagePolicy. It’s Sigstore-native and a natural fit if you’re all-in on the ecosystem.
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
name: require-signed-app
spec:
images:
- glob: "myregistry.io/app**"
authorities:
- key:
data: |
-----BEGIN PUBLIC KEY-----
<contents of cosign.pub>
-----END PUBLIC KEY-----
Namespaces opt in by label (for example policy.sigstore.dev/include: "true"), and any image matching the glob must satisfy at least one authority or be denied. Functionally it lands in the same place as the Kyverno rule: unsigned or wrongly-signed images never schedule.
Exam cue: “Ensure only images signed by our team’s key can run in the cluster” → verify the signature at admission with a policy engine (Kyverno
verifyImagesor the sigstore policy-controller), set to enforce, keyed to yourcosign.pub. Don’t answer “scan the image” — scanning doesn’t check signatures.
A Realistic End-to-End Flow
Tie the pieces together the way you’d defend a real cluster — and the way a scenario question implies:
- Build the image in CI and push it to your registry by digest.
- Scan it with Trivy; fail the pipeline on CRITICAL findings (the detective control).
- Sign the digest with Cosign using a key stored in KMS; optionally attest the SBOM.
- Deploy an admission policy (Kyverno
verifyImagesor policy-controller) inEnforcemode, keyed to your public key. - Result: any pod referencing an image that isn’t signed by your key — a mistyped registry, a tampered image, an old unsigned build — is rejected before it ever runs.
That chain is the whole point of supply chain security: multiple independent gates, each cheap on its own, that together make it hard for an untrusted image to reach a node.
Common Mistakes to Avoid
| Mistake | Why it bites | Fix |
|---|---|---|
| Signing by mutable tag | The tag can be repointed; the signature stops meaning anything | Sign and reason by @sha256: digest |
| Treating a signature as a vulnerability check | A signed image can still be full of CVEs | Scan and verify; they’re different controls |
Leaving the policy in Audit/Warn | It logs violations but still admits bad images | Set Enforce once rollout is validated |
| Storing the private key in the repo or on nodes | Key compromise means anyone can forge “trusted” images | Use KMS or an encrypted Secret; rotate keys |
Confusing verify with verify-attestation | You check the wrong thing and miss the requirement | verify = signed; verify-attestation = signed claim about it |
| Forgetting namespace opt-in (policy-controller) | Pods run unchecked in un-labeled namespaces | Label namespaces so the policy applies |
Frequently Asked Questions
Do I need to know keyless signing (Fulcio/Rekor) for the CKS?
Not to exam depth. The tested skill is key-based signing and verification with Cosign and enforcing it at admission. Keyless signing, Fulcio, and Rekor are valuable real-world Sigstore knowledge but are background context for the exam, not something you’ll be asked to configure.
Where does Cosign store the signature?
In the same OCI registry as the image, as an additional artifact associated with the image’s digest. You don’t run a separate signature database — your registry holds both the image and its signature.
Is signing a replacement for image scanning?
No. Signing proves integrity and provenance; scanning proves the image is free of known vulnerabilities. They’re complementary. A complete supply-chain posture scans and verifies signatures, and enforces both.
Kyverno verifyImages or the sigstore policy-controller — which should I learn?
Understand the concept — verifying a Cosign signature at admission and rejecting failures — because that’s what the exam tests. Kyverno is the more commonly referenced tool because its policies are plain YAML, so lead with it; recognize the policy-controller and ClusterImagePolicy as the Sigstore-native equivalent.
How do I roll this out without breaking every existing workload?
Start the policy in Audit (Kyverno) or apply it to a single opted-in namespace (policy-controller), watch what it would block, sign the images that need to keep running, then switch to Enforce. Enforcing cluster-wide on day one will reject unsigned system and third-party images and cause an outage.
Should I sign by tag or digest?
Always digest. Tags are mutable and a tag-bound signature can be silently invalidated by repointing the tag. Digests are content-addressed and immutable, which is exactly the property a signature needs.
Conclusion & Next Steps
Image signing is the supply-chain control that answers who made this and has it changed — the question scanning can’t. For the CKS, own the key-based Cosign workflow (generate, sign by digest, verify, and verify-attestation), understand where the signature lives, protect the private key, and — most importantly — enforce verification at admission so the cluster rejects anything unsigned. Keep keyless signing and the Fulcio/Rekor machinery as real-world context, not exam memorization.
To practice this against a live cluster under time pressure, Sailor.sh’s Certified Kubernetes Security Specialist (CKS) Mock Exam Bundle provides a browser-based, exam-style terminal with realistic supply-chain scenarios — signing images, wiring up admission policies, and fixing what they reject — so the muscle memory is there on exam day. If you want a free environment to experiment first, the CKS practice environment guide walks through getting started.
Round out the domain and the exam with the CKS Supply Chain Security guide for scanning and base-image hardening, the CKS admission control deep-dive for the broader policy-engine picture, the CKS Study Plan to schedule your prep, and the CKS Exam Guide 2026 for the full blueprint and logistics.