Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 5 min read

How one user's StatefulSet edit could land a pod in someone else's namespace

How one user's StatefulSet edit could land a pod in someone else's namespace On September 23, Kubernetes shipped fixes for CVE-2026-2270, a confused deputy bug in the StatefulSet controller. The short version: a user w

How one user's StatefulSet edit could land a pod in someone else's namespace

On September 23, Kubernetes shipped fixes for CVE-2026-2270, a confused deputy bug in the StatefulSet controller. The short version: a user with write access to StatefulSets and ControllerRevisions in one namespace could get the cluster itself to create a pod in a different namespace. The cluster did the crossing. The user just pointed.

If you run a shared cluster, this one is worth understanding, because the pattern behind it shows up everywhere.

The wall everyone trusts

Namespaces are the walls of Kubernetes. You give team A their own namespace, team B theirs, and RBAC rules make sure nobody reaches across. A user who can only touch team-a should never be able to create anything in team-b. That is the whole promise.

The bug broke that promise. A namespace-scoped user, someone RBAC confined to a single namespace, could end up with a pod running in another namespace entirely. They did not hack RBAC. They did not escalate their own permissions. They asked a more powerful program to do it for them, and it agreed.

That is what "confused deputy" means. The deputy is the StatefulSet controller, a cluster-wide process with the keys to every namespace. It was confused because it trusted data it should not have trusted.

Suspect one: the ControllerRevision

To follow the trail, you need to know what a ControllerRevision is. It is one of those Kubernetes objects most people never touch directly, but it is doing quiet work in the background.

When you update a StatefulSet, say you change the container image from v1 to v2, the controller does not throw away the old configuration. It saves a snapshot of it in a ControllerRevision object. If the rollout goes wrong, the controller can roll back by restoring from that snapshot. Think of it as the "previous versions" feature of a document editor, but for your stateful workloads.

Here is the part that matters: ControllerRevisions are regular API objects, and RBAC can grant users write access to them. In some clusters, especially multi-tenant ones, developers get broad permissions over the workload objects in their namespace, including StatefulSets and their ControllerRevisions. Nothing about that looks dangerous on its own.

Suspect two: the cluster-wide controller

The StatefulSet controller runs inside kube-controller-manager. It is not scoped to any namespace. It cannot be, because its job is to watch StatefulSets everywhere and reconcile them: compare what exists with what is declared, and fix the difference by creating, updating, or deleting pods.

So you have a process with authority over every namespace, and it reads snapshots that ordinary users are allowed to write. If those snapshots can smuggle instructions the controller will act on, the user has effectively borrowed the controller's authority. That is exactly what happened.

The trick

When the controller restored a StatefulSet from a ControllerRevision, it restored more than it should have. The fix tells the story plainly: patched versions ensure that only the spec field is restored from ControllerRevisions. Which means the old code was restoring additional fields, and those extra fields are what carried the attack across the namespace wall.

An attacker with write access to both objects in their own namespace could craft a ControllerRevision containing a StatefulSet whose metadata pointed at a different namespace. The controller, doing its honest reconciliation work, would read the snapshot, restore the fields, and create the pod where the snapshot said to. The attacker would have full control over the resulting pod's metadata and specification, including the namespace selection.

The user's permissions never changed. They could still only write in their own namespace. But the deputy they tricked could write anywhere.

The twist: the garbage collector was watching

There is a catch that kept this from being a wide-open door. Kubernetes has a garbage collector that cleans up orphaned objects. A pod created in another namespace, with no valid owner there, gets deleted almost immediately.

To keep the pod alive, the attacker needed a valid OwnerReference pointing at a real StatefulSet in the victim namespace. An OwnerReference is how a pod says "I belong to this StatefulSet," and the garbage collector checks it. Forging a convincing one requires the UID of an existing StatefulSet in the target namespace. That is not something you can guess from outside.

So the full attack needed two things: the confused deputy trick to place the pod, and knowledge of a real StatefulSet UID in the victim namespace to keep it there. That second requirement is why the advisory notes this matters most in multi-tenant clusters, where that kind of information leaks across tenants more easily, and where broad write permissions get handed out more casually.

The fix

Kubernetes released patched versions on September 23: v1.34.12, v1.35.9, v1.36.5, and v1.37.1. The fix is surgical. The controller now restores only the spec field from ControllerRevisions, cutting off the path that let attacker-controlled metadata cross the wall.

The vulnerability was reported by ImanOracle, and the fix was coordinated by Maciej Szulik, Filip KΕ™epinskΓ½, VerΓ³nica LΓ³pez, Jeremy Rickard, and Nathan Herz. No confirmed exploitation has been reported. The CVSS score is 5.9, medium, which reflects the high privileges required and the garbage collector catch, not the seriousness of the boundary it crossed.

If you cannot upgrade immediately, the advisory's guidance is direct: treat StatefulSet and ControllerRevision write access as sensitive. That combination of permissions is more powerful than it looks.

The lesson that outlives the CVE

This bug will be patched and forgotten, but the pattern will not. Every system has deputies: CI runners that deploy with production credentials, webhooks that act on user-supplied payloads, controllers that reconcile user-written objects with cluster-wide authority. The confused deputy shows up whenever a powerful helper acts on data from a less powerful user without checking whether the user was allowed to ask for that outcome.

Namespaces are still the right walls. RBAC is still the right lock. But a lock is only as good as the most trusted person holding a key, and in Kubernetes, controllers hold keys to everything. Audit who can write the objects your controllers read. In this case, that meant one RBAC review:

kubectl auth can-i create statefulsets --as=team-a-dev -n team-a
kubectl auth can-i create controllerrevisions --as=team-a-dev -n team-a

If both of those return yes for users who do not need that combination, you had the same shape of problem, with or without this CVE.

When was the last time you checked which roles in your cluster can write ControllerRevisions?

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.