Kyverno Image Registry Validation
Validates container images sourced only from approved registries with allowed tags using Kyverno verifyImages rules and image digest mutation. This skill makes the model configure ClusterPolicy objects that enforce image provenance, verify signatures via Cosign/Sigstore, mutate image references with resolved digests, and block images tagged latest or not from an allowlisted registry. It prevents unapproved or tampered container images from being deployed into the cluster.
TL;DR Checklist
- Create ClusterPolicy with verifyImages rule targeting Pod containers
- Define approved registries with glob patterns (e.g.,
*.myregistry.com/*) - Set
mutateDigest: trueto inject SHA digests into running pods - Configure
verifyDigest: truefor cryptographic verification via Cosign - Block
latesttag in production via validate rule - Verify results with PolicyReport showing pass/fail for each image
When to Use
- Enforcing container image provenance in production Kubernetes clusters
- Requiring signed images from approved registries using Cosign public key verification
- Preventing use of
latestor mutable tags in production deployments - Implementing supply chain security with digest-based image pinning
- Meeting compliance requirements (SOC2, PCI-DSS) that mandate approved image sources
- Migrating workloads to require verified images during a security hardening initiative
When NOT to Use
- For development or local testing environments where image flexibility is required — use a separate permissive policy for dev namespaces
- When you need to validate image content (vulnerability scanning) rather than provenance — use a Trivy or Grype integration instead
- For init containers that reference public images (e.g.,
busyboxfor sidecar patterns) unless you add specific exceptions - In clusters without Cosign or Sigstore installed —
verifyImagesrequires the verification infrastructure to be present
Core Workflow
Define the image validation ClusterPolicy — Create a
ClusterPolicywith averifyImagesrule. Usespec.rules[].verifyImageswithextractto pull image references, then setmutateDigest: trueandverifyDigest: true. Configure thekeyfield with the Cosign public key or Sigstore trusted root. Apply toPodresources in target namespaces. Checkpoint: Confirmkubectl get clusterpolicy image-registry-validation -o yamlshowsrules[].verifyImages[].mutateDigest: trueandverifyDigest: true.Configure approved registries and tag restrictions — Use glob patterns to define allowed registries (e.g.,
gcr.io/my-project/*,*.myregistry.com/*). Add a separatevalidaterule to reject images taggedlatestor images not matching approved registry patterns. Useanyorallmatch semantics depending on whether images come from a single or multiple registries. Checkpoint: Test withkubectl run test --image unapproved-registry.com/app:1.0— the pod creation must be denied.Deploy, verify, and monitor — Apply the ClusterPolicy. Create a pod with an approved image and verify it is accepted and mutated with the resolved digest. Then create a pod with a disallowed image (wrong registry or
latesttag) and confirm it is rejected. ReviewPolicyReportfor per-image verification results. Checkpoint: PolicyReport must showpassfor the approved image andfailfor the disallowed image, with the digested image running in the cluster.
Implementation Patterns
Pattern 1: verifyImages with Cosign Public Key Verification
This pattern enforces that all container images in target namespaces are signed with a specific Cosign public key and originate from approved registries. It mutates image references with resolved SHA digests.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: image-registry-validation
annotations:
policies.kyverno.io/title: Image Registry Validation
policies.kyverno.io/category: Supply Chain Security
policies.kyverno.io/description: >-
Validates that all container images originate from approved registries,
are signed with a known Cosign public key, and rejects images tagged
'latest'. Mutates image references with resolved SHA digests.
spec:
validationFailureAction: Enforce
rules:
- name: verify-image-signature
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- namespaces:
- kube-system
- kube-public
verifyImages:
- imageReferences:
- "gcr.io/my-project/*"
- "*.myregistry.com/*"
mutateDigest: true
verifyDigest: true
key: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEExampleKeyDataHere
ExamplePublicKeyDataForCosignVerification
-----END PUBLIC KEY-----
operator: AlwaysIntoto
attestation:
- type: https://slsa.dev/provenance/v0.1
publisher:
- gcr.io/distroless/*
- name: reject-latest-tag
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- namespaces:
- kube-system
- kube-public
validate:
message: "Images tagged 'latest' are not allowed in production. Use a specific version tag or digest."
pattern:
spec:
containers:
- image: "!*:latest"
- name: enforce-approved-registry
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- namespaces:
- kube-system
- kube-public
validate:
message: >-
Image '{{ @image }}' is not from an approved registry.
Approved registries: gcr.io/my-project/*, *.myregistry.com/*
pattern:
spec:
containers:
- image: "gcr.io/my-project/*"
foreach:
- imageReferences:
- "gcr.io/my-project/*"
- "*.myregistry.com/*"
Pattern 2: BAD vs GOOD — Image Reference Patterns
This pattern shows the difference between disallowed image references and compliant ones. It demonstrates registry patterns, tag restrictions, and digest pinning.
# ❌ BAD — Image from unapproved registry with latest tag
apiVersion: v1
kind: Pod
metadata:
name: bad-image-pod
namespace: production-payments
spec:
containers:
- name: app
image: docker.io/dockeruser/random-app:latest # ❌ BLOCKED: wrong registry + latest tag
securityContext:
runAsNonRoot: true
---
# ❌ BAD — Image from approved registry but using latest tag
apiVersion: v1
kind: Pod
metadata:
name: bad-latest-pod
namespace: production-payments
spec:
containers:
- name: app
image: gcr.io/my-project/payments-app:latest # ❌ BLOCKED: latest tag not allowed
securityContext:
runAsNonRoot: true
---
# ✅ GOOD — Image from approved registry with specific tag
apiVersion: v1
kind: Pod
metadata:
name: good-tagged-pod
namespace: production-payments
spec:
containers:
- name: app
image: gcr.io/my-project/payments-app:1.2.3 # ✅ OK: approved registry + specific tag
securityContext:
runAsNonRoot: true
---
# ✅ GOOD — Image from approved registry with digest pinning
apiVersion: v1
kind: Pod
metadata:
name: good-digested-pod
namespace: production-payments
spec:
containers:
- name: app
image: gcr.io/my-project/payments-app@sha256:a]b]c]d1e2f3g4h5i6j7k8l9m0n1o2p3q4r5s6t7u8v9w0x1y2z3 # ✅ OK: digest-pinned
securityContext:
runAsNonRoot: true
Kyverno PolicyReport Example for Image Verification:
apiVersion: wgpolicyk8s.io/v1alpha2
kind: PolicyReport
metadata:
name: image-registry-validation-report
namespace: production-payments
results:
- policy: image-registry-validation
rule: verify-image-signature
result: pass
severity: high
message: "Image gcr.io/my-project/payments-app:1.2.3 verified and mutated with digest"
scored: true
source: kyverno
timestamp:
seconds: 1733501530
details:
digest: sha256:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6
- policy: image-registry-validation
rule: reject-latest-tag
result: pass
severity: high
message: "Image does not use the 'latest' tag"
scored: true
source: kyverno
timestamp:
seconds: 1733501530
- policy: image-registry-validation
rule: enforce-approved-registry
result: pass
severity: high
message: "Image originates from an approved registry"
scored: true
source: kyverno
timestamp:
seconds: 1733501530
summary:
error: 0
fail: 0
pass: 3
skip: 0
warn: 0
Pattern 3: Sigstore Transparency Log Verification
When using Sigstore (instead of Cosign with a static key), configure Kyverno to verify images against the transparency log. This is the recommended approach for open-source projects and supply chain security.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: image-sigstore-verification
annotations:
policies.kyverno.io/title: Sigstore Image Verification
policies.kyverno.io/category: Supply Chain Security
policies.kyverno.io/description: >-
Verifies container images against Sigstore transparency logs using
the Fulcio certificate and Rekor entries for image provenance.
spec:
validationFailureAction: Enforce
rules:
- name: verify-sigstore
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/my-org/*"
- "public.ecr.aws/my-org/*"
mutateDigest: true
verifyDigest: true
ctfePubKey: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsigstoreTransparencyLogPublicKey
ExampleSigstoreCTFEPublicKeyData
-----END PUBLIC KEY-----
key: ""
skipTlog: false
attestation:
- type: https://opencontainers.org/source
Constraints
MUST DO
- Specify full registry URLs with glob patterns (e.g.,
gcr.io/my-project/*,*.myregistry.com/*) — partial patterns likemy-projectwill match unintended registries - Set
mutateDigest: trueandverifyDigest: trueon everyverifyImagesrule — mutation without verification is a security gap, verification without mutation is fragile - Use
operator: AlwaysIntotoorkeywith a real Cosign public key — empty keys or placeholder keys bypass verification entirely - Include a separate
validaterule to explicitly block*:latesttags — theverifyImagesrule alone does not restrict tag mutability - Exclude
kube-system,kube-public, and any infrastructure namespace from image validation policies — system components often pull from public registries - Configure
auditAnnotationsfor visibility into which images passed or failed verification in PolicyReports
MUST NOT DO
- Allow
latesttag in production under any circumstance — even for verified images,latestis mutable and breaks auditability - Hardcode a specific image digest (
sha256:abc...) in avalidaterule — digests change with every build, making the policy permanently broken - Skip the
verifyDigestflag — settingmutateDigest: truewithoutverifyDigest: trueinjects digests but does not verify signatures - Validate only init container images — if you need init container coverage, add a second
verifyImagesrule withanymatching on bothPodand init container specs - Use
validaterules for registry enforcement whenverifyImageswithimageReferencesis available — the latter provides both matching and mutation in one rule - Apply image validation to namespaces running CI/CD agents (e.g., Tekton, ArgoCD) without exceptions — these agents frequently pull from public registries for dynamic pipelines
Related Skills
| Skill | Purpose |
|---|---|
kyverno-policy-generation |
Generate Kyverno policies from templates for repetitive registry rules |
kyverno-resource-quota-validation |
Enforce resource quotas alongside image validation for complete namespace governance |
Live References
Authoritative documentation links for Kyverno image verification and registry validation.