Safeguard
Tools

Best Kubernetes Admission Controllers for Supply Chain Security

Kyverno, OPA Gatekeeper, Sigstore policy-controller, Ratify, or plain CEL? A field guide to admission controllers that actually block unsigned and vulnerable images.

Priya Raman
Staff Security Engineer
Updated 6 min read

The best Kubernetes admission controller for supply chain security is the one that verifies image signatures and provenance before a pod schedules — Kyverno for most teams, Sigstore policy-controller for signature-heavy shops, OPA Gatekeeper plus Ratify where Rego is already entrenched, and native ValidatingAdmissionPolicy when you want zero extra components. Admission is the last enforcement point you own: after the API server admits a pod, you are in detection territory, not prevention.

Scanning in CI is necessary but insufficient. Images reach clusters through hotfix pushes, third-party Helm charts, and that one team that still does kubectl run against prod. An admission webhook doesn't care how the image arrived; it evaluates every CREATE on pods and either admits or rejects. Here is how the field actually compares in 2026.

Kyverno: the pragmatic default

Kyverno policies are Kubernetes YAML, which means platform teams can read and review them without learning a policy language. Its verifyImages rule type does cosign and notation signature verification, attestation checks, and digest mutation in one place:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-signed-images
spec:
  validationFailureAction: Enforce
  webhookTimeoutSeconds: 15
  rules:
    - name: verify-signature
      match:
        any:
          - resources:
              kinds: ["Pod"]
      verifyImages:
        - imageReferences: ["ghcr.io/acme/*"]
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/acme/*"
                    issuer: "https://token.actions.githubusercontent.com"

That policy enforces keyless cosign signatures from your own GitHub Actions builds. Kyverno also mutates image tags to digests on admission, which kills tag-mutation attacks as a side effect. Weak spot: complex logic gets awkward in YAML, and heavy verifyImages policies add tens of milliseconds per pod admission, so set webhookTimeoutSeconds deliberately and always configure failurePolicy with eyes open.

OPA Gatekeeper + Ratify: for Rego shops

Gatekeeper is the incumbent. If your org already writes Rego for Terraform or API authorization, reusing the skill is worth real money. Gatekeeper alone cannot verify signatures — it evaluates structure, not cryptography — so pair it with Ratify, a CNCF verification engine that checks cosign/notation signatures, SBOM presence, and vulnerability attestations, then exposes the verdict as data Gatekeeper constraints can act on.

The tradeoff is operational surface: two deployments, two upgrade cadences, and Rego's learning curve, which is not small. Teams that adopt Gatekeeper without prior Rego experience routinely end up with a single overworked policy author as a bus-factor-one dependency.

Sigstore policy-controller: signature verification, done narrowly

The Sigstore project's own admission controller does one thing: enforce ClusterImagePolicy resources that require signatures or attestations (SLSA provenance, SPDX/CycloneDX SBOMs, vulnerability scan attestations) on matching images. Because it is built by the people who build cosign, keyless verification against Fulcio and Rekor is first-class rather than bolted on. If your supply chain story is "everything is signed keyless in CI, verify it at admission," this is the sharpest tool. It deliberately does not do general policy — you will still want Kyverno or Gatekeeper for pod security and config hygiene, and running two webhook chains is a real cost. Our walkthrough on enforcing cosign signatures in Kubernetes admission covers the setup end to end.

ValidatingAdmissionPolicy: native CEL, zero webhooks

Since Kubernetes 1.30, ValidatingAdmissionPolicy (CEL expressions evaluated in-process by the API server) is GA. No webhook, no TLS certs, no availability tradeoff — a policy like "images must come from registry.acme.io and must be pinned by digest" is a dozen lines of CEL:

validations:
  - expression: >-
      object.spec.containers.all(c,
        c.image.startsWith('registry.acme.io/') &&
        c.image.contains('@sha256:'))

What CEL cannot do is cryptography or external lookups, so signature verification and live vulnerability checks stay out of reach. Use it as the always-on floor (registry allowlist, digest pinning, no latest), with a webhook controller layered above for verification.

Scanner-integrated admission: the vulnerability gate

A separate category checks the image's scan state at admission: is there a fresh SBOM, does it carry critical CVEs, does it pass policy? Trivy's operator ecosystem approaches this from the open-source side. Commercial platforms — Safeguard among them — ship an admission component that queries the platform's scan verdict for the exact digest being admitted and blocks images that were never scanned or that exceed a severity budget, which closes the "scanned in CI three weeks ago, CVE published yesterday" gap. If findings volume is what's stopping you from turning enforcement on, gate on reachability-filtered results rather than raw CVE counts; blocking on every medium CVE in a base image is how admission controllers get uninstalled by Friday.

Comparison at a glance

ControllerPolicy languageSignature verificationVuln/SBOM gatingOperational weight
KyvernoYAML (declarative)Yes (cosign, notation)Via attestationsLow-medium
Gatekeeper + RatifyRegoYes (via Ratify)Via Ratify verifiersMedium-high
Sigstore policy-controllerClusterImagePolicy CRDYes (native, keyless-first)Via attestationsLow, narrow scope
ValidatingAdmissionPolicyCEL (in-process)NoNoNear zero
Scanner-integrated (Trivy, Safeguard)Platform policySometimesYes, live verdictsMedium

Whichever Kubernetes admission controller you deploy: start in audit mode, watch a week of would-have-blocked events, then flip to enforce namespace by namespace. And decide your failurePolicy before the first API-server incident, not during it — Fail closed on a down webhook means no pod admits cluster-wide, including the pods that would fix the webhook.

Frequently asked questions

Can I run Kyverno and the Sigstore policy-controller together?

Yes, and plenty of teams do: policy-controller owns signature and attestation verification while Kyverno handles mutation, pod security, and config policy. Scope each webhook's matchConditions tightly so images aren't verified twice, and keep timeout budgets short since webhook latency stacks.

Should admission controllers fail open or fail closed?

Fail closed (failurePolicy: Fail) for supply chain policies in production namespaces, fail open in system namespaces so the cluster can heal itself. Exempt kube-system and your controller's own namespace explicitly — a signature webhook that blocks its own re-deployment is a genuinely bad afternoon.

Is admission control redundant if we already scan in CI?

No — CI scanning is point-in-time and only covers images that went through your pipeline. Admission control catches side-loaded images, stale scans, and CVEs published after the build, which is where the interesting incidents live.

How much latency does image verification add to pod creation?

Keyless cosign verification typically adds 50-300 ms per unique image, dominated by Rekor lookups; verdicts are cached, so replicas of the same digest admit in single-digit milliseconds. Set webhookTimeoutSeconds around 15 for verification policies and monitor webhook p99 like any other production dependency.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.