Hardening · Workload policy

Admission Control

RBAC decides whether a tenant can create a pod. Admission control decides what that pod is allowed to look like, and it's where most of the "just ask for privileged" breakouts get stopped.

If a tenant can write their own pod specs, then without admission control they can ask for privileged: true, a hostPath mount of the node’s filesystem, or the host’s PID and network namespaces, and Kubernetes will happily give it to them. That’s the increased pod rights problem, and admission control is the main fix for it.

Pod Security Admission

The built-in starting point is Pod Security Admission (PSA), which has been GA since Kubernetes 1.25. It applies one of the three Pod Security Standards (privileged, baseline or restricted) to each namespace, based on a label like pod-security.kubernetes.io/enforce: restricted.

For tenant namespaces, restricted is the one to aim for, with baseline as a fallback for workloads that can’t run under it. PSA runs inside the API server, so there’s no webhook to go down, and it has warn and audit modes that make it a lot easier to roll out gradually.

It’s deliberately simple though. You get three profiles, applied per namespace, with no custom rules and no way of looking at anything other than pods.

Policy engines

For everything else there are policy engines like Kyverno and OPA Gatekeeper, or the built-in ValidatingAdmissionPolicy (GA in 1.30), which lets you write rules in CEL without running a webhook at all.

In a multi-tenant cluster there are a couple of rules that come up again and again:

  • Protect the namespace labels. Stop tenants changing the pod-security.kubernetes.io/* labels on their own namespace, otherwise they can switch PSA off for themselves.
  • Block ExternalIP services, either with the DenyServiceExternalIPs admission controller or a policy, to close off CVE-2020-8554.
  • Enforce node placement, so tenants can’t add tolerations or node selectors that land them on another tenant’s node pool.
  • Enforce the runtime, if you’re using sandboxed runtimes, so tenants can’t just leave out the runtimeClassName.
  • Restrict registries and set imagePullPolicy: Always for tenant workloads.
  • Constrain shared components, e.g. forbidding the Istio mesh gateway or limiting the hosts a tenant’s routes can use, and restricting URL fields in operator custom resources to approved destinations.

Making it stick

Admission control has a fair few ways of quietly not applying, so it’s worth checking:

  • Tenants can’t change the policies. Anyone who can edit webhook configurations or cluster-wide policies can switch them off or set them to fail open.
  • Webhooks fail closed for the policies that matter. If a webhook is set to Ignore and goes down, everything gets through.
  • Policies cover every container field. Rules that only check containers can miss initContainers and ephemeralContainers.
  • Namespace selectors use identity. Scope policies with the kubernetes.io/metadata.name label rather than a custom label a tenant could add or remove, and make sure tenants can’t deploy into exempt namespaces like kube-system.
  • Allowlists over blocklists. A blocklist has to be updated every time Kubernetes adds a new feature, an allowlist doesn’t.

What admission control doesn’t fix

  • Kernel exploits. A pod that fully complies with restricted is still sharing the node’s kernel. Admission control stops the easy breakouts, not the hard ones.
  • Anything that doesn’t go through the API server. Static pods are created directly by the kubelet, so someone with node access can skip admission entirely.
  • The runtime doing something different. Admission checks the pod that was requested. The 2026 checkpoint/restore CVEs in containerd, CRI-O and Podman let a checkpoint image restore with its own root, capabilities and seccomp settings, so a pod that passed restricted could run with full privileges.
  • The policy engine itself. Policy engines are cluster-wide operators that evaluate tenant-supplied rules, and Kyverno and Kubewarden both had cross-tenant CVEs in 2026. They’re part of the operator attack surface too.

References & further reading

← All hardening techniques