Kubernetes Security in 2026: First Attack in 18 Minutes, and What Stops It
The first thing I do when someone hands me a Kubernetes cluster to review is not run a scanner. I run kubectl auth can-i --list --as=system:anonymous and look at what an unauthenticated stranger is allowed to do, then I look for anything with a public IP that was installed from a Helm chart with default values. Those two checks find more real problems than most dashboards full of CVE counts, because Kubernetes security in 2026 is still mostly about configuration, not zero-days. This post walks through how clusters actually get attacked today (with sources), what the survey numbers from Red Hat and Wiz say, and which controls have matured enough this year to be worth turning on: Pod Security Standards, user namespaces, the CIS benchmark, image signing and network policy.
How are Kubernetes clusters actually attacked in 2026?
Four patterns account for nearly every public incident write-up I have read in the last two years.
Anonymous API access plus a careless RBAC binding. A public API server with anonymous authentication is not a breach by itself. It becomes one when someone binds a role to system:anonymous or the system:unauthenticated group. Wiz's June 2024 write-up of a DERO cryptojacking campaign describes exactly that path: an externally reachable API server, extra permissions on the anonymous identity, then DaemonSets with harmless-sounding names like pytorch-container and k8s-device-plugin running miners pulled from Docker Hub images with more than 10,000 pulls. Aqua's earlier "RBAC Buster" campaign used the same entry point and then created its own RBAC objects for persistence.
Exposed dashboards and default Helm charts. The Kubernetes Dashboard is now archived, and the project's own blog points users to Headlamp. Archived software does not get uninstalled by itself, though, so old Dashboard deployments with permissive service accounts are still out there. The broader version of this problem is charts that ship convenient defaults. Microsoft's Defender for Cloud researchers showed in May 2025 that several popular charts expose services through LoadBalancer with no authentication by default, Apache Pinot being their example.
Vulnerable cluster components. IngressNightmare (covered below) is the textbook case: an unauthenticated admission webhook inside the cluster that any pod could reach.
Application exploit, then token theft, then node escape. This is the pattern that worries me most, because it starts outside Kubernetes. Wiz's threat catalogue records a June 2026 campaign that exploited 1-day bugs in Argo Workflows and Gogs, deployed miners, and used stolen service account tokens and privileged container escapes to reach more than 300 additional nodes in ten days. Nothing in that chain needs a Kubernetes CVE. It needs a pod with a mounted token that can do too much, and a pod allowed to run privileged.
Speed matters here. Wiz's 2025 Kubernetes Security Report, built from more than 200,000 cloud accounts, says new AKS clusters see their first attack attempt within 18 minutes and EKS clusters within 28. You do not get a quiet week to harden a cluster after creating it. The guardrails have to be in the template.
What do the Kubernetes security surveys say?
The most cited survey is Red Hat's State of Kubernetes Security report. The latest edition I could find is the 2024 report, based on 600 DevOps, engineering and security professionals surveyed in December 2023 and January 2024. I looked for a 2025 or 2026 edition and did not find one, so treat these as the most recent numbers from that series rather than this year's.
Two things stand out. First, the incident mix is evenly spread: 45% runtime incidents, 44% major vulnerabilities, 40% misconfigurations. No single tool category covers that. Second, the cost lands on delivery: 67% delayed or slowed deployments because of security concerns, which is the strongest argument I know for putting guardrails into the platform instead of into review meetings.
Wiz's numbers are about hygiene. 81% of EKS clusters still use the deprecated aws-auth ConfigMap for authentication, and only 54% of clusters run a supported Kubernetes version (up from 42%). An unsupported cluster cannot receive the features discussed below, so version currency is a security control in its own right. My post on whether Kubernetes is still worth it in 2026 covers the upgrade cost side.
| Finding | Number | Source |
|---|---|---|
| Orgs with at least one container or Kubernetes incident in 12 months | 89% | Red Hat 2024 |
| Orgs that delayed or slowed deployment over security | 67% | Red Hat 2024 |
| Time to first attack, new AKS / EKS cluster | 18 / 28 min | Wiz 2025 |
| EKS clusters on deprecated aws-auth | 81% | Wiz 2025 |
| Cloud environments vulnerable to IngressNightmare at disclosure | about 43% | Wiz, March 2025 |
| Clusters exposing the vulnerable admission webhook to the internet | 6,500+ | Wiz, March 2025 |
| Cloud native environments relying on ingress-nginx (Datadog data) | about 50% | Kubernetes Steering and SRC, Jan 2026 |
What was IngressNightmare, and why does it still matter?
Wiz disclosed IngressNightmare on 24 March 2025: CVE-2025-1974 plus three injection bugs (CVE-2025-1097, CVE-2025-1098, CVE-2025-24514), chained to a CVSS 9.8 unauthenticated remote code execution in the ingress-nginx admission controller. The root cause is worth remembering because it generalises. The admission webhook was an unauthenticated HTTP endpoint reachable from any pod on the cluster network, and the controller's service account could read every Secret in the cluster. One compromised pod anywhere became cluster takeover. Fixed versions were 1.12.1 and 1.11.5.
The sequel is the retirement. ingress-nginx was retired in March 2026, and the joint statement from the Steering and Security Response Committees is blunt: no more releases of any kind, including security patches, for software that about half of cloud native environments depended on. They give a one-line check: kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx. If that returns pods today, you are running an internet-facing component that will never be patched again. The migration options are in Ingress NGINX Is Retired: What Replaces It.
The lesson for everything else: an in-cluster webhook or API that trusts the pod network is an attack surface. A default-deny network policy that only lets the API server reach the webhook would have turned IngressNightmare from "any pod" into "nobody". My companion post, How to Write Kubernetes NetworkPolicies, walks through exactly that.
Which RBAC misconfigurations do attackers look for?
The same handful, every time:
- Any binding to
system:anonymousorsystem:unauthenticatedbeyond the defaults. Out of the box the unauthenticated group gets onlysystem:public-info-viewer, which exposes version and health information. Anything more is a finding. - Service accounts with
cluster-admin, or withlist/getonsecretscluster-wide. Ingress controllers, CI runners and operators are the usual offenders. createonpodsorpods/execin a namespace that also allows privileged pods. That is node access by another name.nodes/proxy. Until recently, monitoring agents needed it to read kubelet metrics, and it also allowed exec into any container on the node. Fine-grained kubelet API authorization went GA in Kubernetes 1.36, so agents can be granted narrower subresources instead.
Since Kubernetes 1.34 you can also restrict anonymous authentication to specific paths with the AuthenticationConfiguration file (the AnonymousAuthConfigurableEndpoints gate is stable and locked on), keeping /livez, /readyz and /healthz open and nothing else. On managed services you usually cannot change API server flags, which makes the RBAC audit the control you actually own.
Here is the quick audit I run, followed by a namespace baseline. It assumes kubectl and jq, and a cluster on a supported version (1.35, 1.36 or 1.37 as of today).
#!/usr/bin/env bash
# Kubernetes quick security audit. Read-only, needs cluster-admin to see everything.
set -euo pipefail
# 1. What can an unauthenticated caller do? Expect only discovery-style non-resource URLs.
kubectl auth can-i --list --as=system:anonymous --as-group=system:unauthenticated
# 2. Bindings that grant anything to anonymous or unauthenticated subjects.
# Expected on a clean cluster: only system:public-info-viewer.
kubectl get clusterrolebindings,rolebindings -A -o json | jq -r '
.items[] | select(any(.subjects[]?; .name=="system:anonymous" or .name=="system:unauthenticated"))
| "\(.kind)/\(.metadata.name) -> \(.roleRef.name)"'
# 3. Every subject bound to cluster-admin.
kubectl get clusterrolebindings -o json | jq -r '
.items[] | select(.roleRef.name=="cluster-admin")
| .metadata.name + ": " + ([.subjects[]? | "\(.kind)/\(.name)"] | join(", "))'
# 4. Retired ingress-nginx still running? (Steering/SRC check, Jan 2026)
kubectl get pods -A --selector app.kubernetes.io/name=ingress-nginx
# 5. CIS benchmark on a self-managed control plane node (kube-bench v0.16.0, Aug 2026).
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/v0.16.0/job.yaml
kubectl logs job/kube-bench
# Namespace baseline: Pod Security Admission "restricted", pinned to a version.
apiVersion: v1
kind: Namespace
metadata:
name: payments
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.37
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
---
# A pod that passes "restricted" and runs in its own user namespace (GA in 1.36).
apiVersion: v1
kind: Pod
metadata:
name: api
namespace: payments
spec:
hostUsers: false # container root is not host root
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: api
image: registry.example.com/payments/api@sha256:REPLACE_WITH_DIGEST
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
Pod Security Standards and user namespaces: what changed in 2026?
Pod Security Admission has been stable since 1.25, and it is still the cheapest control in Kubernetes: three labels per namespace, no extra software. restricted blocks privileged pods, host namespaces, hostPath volumes and privilege escalation, which removes the "privileged container escape" step from the 2026 campaign above. Start with warn and audit across the cluster, fix what shows up, then flip enforce. Pin enforce-version so a control plane upgrade does not silently change what passes.
The bigger change is user namespaces. They reached GA in Kubernetes 1.36 in April, after being on by default since 1.33. Setting hostUsers: false maps UID 0 inside the container to an unprivileged UID on the host, using ID-mapped mounts so volumes do not need a recursive chown. A process that breaks out of the container is no longer root on the node. It is Linux-only and needs a reasonably recent kernel and runtime, but for most stateless workloads it is a one-line change. Kubernetes 1.37 went further with rootless kubelet (KubeletInUserNamespace) at beta.
User namespaces are not a sandbox. The kernel is still shared, and a kernel bug is still a kernel bug. For genuinely untrusted code (AI agents executing generated code, customer scripts) you want a separate kernel per workload. I compare the options in Container vs microVM vs gVisor; disclosure, I run PandaStack, a Firecracker microVM platform, so I have a view on this.
Is the CIS Kubernetes Benchmark still worth running?
Yes, with a caveat about timing. kube-bench, the usual open-source runner, maps CIS Kubernetes Benchmark 1.12 to Kubernetes 1.32 and 1.33, and its latest release is v0.16.0 from August 2026. Supported upstream releases are now 1.35 to 1.37, so the newest generic benchmark trails the versions you should be running by two or more minors. Managed distributions have their own profiles (EKS 1.8, GKE 1.9 and others are in kube-bench), which are more useful than the generic one if you are on a managed service.
What CIS is good at: control plane flags, file permissions, kubelet settings, audit logging. What it cannot see: your RBAC intent, your Helm values, or whether a pod can reach a webhook it should not. I run it on every new node image and at upgrade time, and I do not treat a clean report as evidence that a cluster is secure.
Image signing and supply chain: what can you enforce today?
Kubernetes itself signs its release binaries and images with cosign keyless signing, and the docs show how to verify them. For your own images, the enforcement point is admission: Kyverno (v1.19.1 at the time of writing) or Sigstore's policy-controller can reject pods whose image is not signed by your CI identity. Wiz's DERO write-up lists signature verification and registry allowlists as mitigations for exactly the Docker Hub miner images they found.
Two upstream features help at the edges. KubeletEnsureSecretPulledImages has been beta and on by default since 1.35: a pod can no longer use a private image already cached on the node unless it has credentials for it. And in 1.37, Pod Certificates and ClusterTrustBundles went stable, giving workloads short-lived X.509 identities from a projected volume rather than long-lived bearer tokens. The wider supply-chain picture, including SBOM and attestation rates, is in my CRA and Sigstore post.
FAQ
What is the biggest Kubernetes security risk in 2026?
Misconfiguration, not exotic exploits. Red Hat's survey found 40% of organisations detected misconfigurations in a year, and the public attack write-ups mostly start with anonymous access, over-permissive RBAC or a service exposed by a default Helm value. Fix RBAC and exposure before buying runtime tools.
Are Kubernetes user namespaces production ready?
Yes, on Linux. They are GA in Kubernetes 1.36 and were enabled by default from 1.33. You opt in per pod with hostUsers: false; your node kernel and container runtime must support ID-mapped mounts for the volumes you use.
Do I still need network policies if I use Pod Security Standards?
Yes. Pod Security Standards limit what a pod can do on its node; network policies limit who it can talk to. IngressNightmare was exploitable from any pod precisely because nothing restricted traffic to the admission webhook. See the network policies guide.
How do I check if my cluster allows anonymous access?
Run kubectl auth can-i --list --as=system:anonymous --as-group=system:unauthenticated and list any role bindings whose subjects include system:anonymous or system:unauthenticated. On a default cluster you should see only system:public-info-viewer.
This quarter, if I were inheriting a fleet, I would do four things in order: run the RBAC audit above and delete every anonymous or surprise cluster-admin binding; find and replace any ingress-nginx still running; put restricted Pod Security labels in warn mode on every namespace and move the clean ones to enforce; and add a default-deny network policy to the namespaces that host webhooks and controllers. None of that is new, and none of it needs AI. It is the boring platform work that decides whether an 18-minute probe finds anything.
Related: Container vs microVM vs gVisor: Choosing Agent Isolation, Kubernetes as the Agent Control Plane in 2026 and CRA Reporting Went Live on 11 September.
I'm Ajay Kumar — I build and operate PandaStack, an open-source Firecracker microVM cloud for AI agents, and write about the infrastructure and tooling around it.
Need this kind of infrastructure work? See what I do or email hello@ajayk.sh.
Related
TLS Certificate Lifetimes in 2026: 200 Days Now, 47 Days by 2029
CA/Browser Forum ballot SC-081 cut public TLS certificates to 200 days on 15 March 2026, then 100 days in 2027 and 47 days in 2029. What changed, what Let's Encrypt did (no OCSP, 6-day certs, ACME profiles, 45 days), and how ARI keeps renewals safe.
11 minOct 20, 2026How to Set Up cert-manager with Let's Encrypt and Fix Errors (2026)
Install cert-manager v1.21 with Helm, create Let's Encrypt ClusterIssuers for HTTP-01 (Gateway API or Ingress) and DNS-01, then debug a Certificate stuck not ready by walking CertificateRequest, Order and Challenge, with rate limits, ARI and alerts.
14 minOct 20, 2026Hardened Container Images in 2026: DHI Free, Bitnami Gone, 515 CVEs to 0
Container base images in 2026 compared: Docker Hardened Images went free under Apache 2.0, Bitnami moved its catalog to bitnamilegacy, Chainguard cut its free tier to five images, and a grype scan of 12 base images found 515 CVEs in python:3.13 and zero in four minimal images.
12 min