← writing

An AI Agent Already Escaped Kubernetes. Is Your Cluster Next?

In May 2026, an LLM harness with no human in the loop broke out of a container, replayed a stolen service-account token, and dumped a Kubernetes cluster's entire Secret store. Kubernetes was never built to contain that. Here's the blast radius, and how to close it.


[Disclaimer: The opinions, insights, and perspectives shared here are solely my own and do not reflect those of my current or past employers, nor do they convey any confidential information by any means.]

On May 29, 2026, Sysdig’s threat research team watched an LLM harness, with no human at the keyboard, exploit a vulnerable marimo notebook (CVE-2026-39987), enumerate the host’s Docker socket, and use it as an escape primitive to break out to the underlying host.1 From there it read the host’s shadow file and SSH keys, then replayed a stolen Kubernetes service-account token to dump the cluster’s entire Secret store. At every step, the harness chose its next move based on what the previous step returned, the way an agent picks its next tool call, not the way a pre-scripted exploit runs down a fixed list. Sysdig calls this an “agentic threat actor,” and their own framing of why it matters is blunt: it’s the first operator they’ve observed where an agent harness, not a human, performs the container escape and the credential replay.1 Nothing about the vulnerability itself was novel. What was new is that nothing with a keyboard chose any of it.

I want to sit with that for a second before getting into the fix, because the fix is easy to nod along to and then forget by the next meeting. A compromised web service is a bounded problem: worst case, it does something the service’s own code was already capable of doing. A compromised agent isn’t bounded that way. It holds a live credential, it has tools it can call on its own initiative, and it makes its own decisions about what to try next based on what it finds. Redirect it with a prompt injection or a poisoned tool response, and it can be pushed into taking actions nobody wrote code for at all. That’s the actual thesis of this piece: Kubernetes was built to isolate stateless services that respond to requests and don’t go looking for more access on their own. An autonomous agent breaks that assumption completely, and when one is compromised, the attacker doesn’t just get code execution in a pod. They inherit everything the agent itself was trusted with: its tools, its credentials, its authority to act.

To make this concrete, I’ll run one example through all three layers where that blast radius actually opens: Ledger, a fictional legacy billing platform that an autonomous agent is migrating to Kubernetes. Ledger isn’t a real system or codebase. It’s a stand-in, built to be safe to discuss in public, so the mechanics stay concrete without describing anyone’s actual production environment.

1 · Permissions 2 · Tools 3 · Runtime Agent
The Agent Blast Radius: where a compromised agent's authority actually goes.

Layer 1: Permissions

Here’s the mechanism, precisely, because it’s easy to wave your hands at “RBAC” and move on. Kubernetes auto-mounts a service-account token into every pod at startup, by default, whether that pod needs it or not (automountServiceAccountToken: true). If that service account is bound to a ClusterRole instead of a namespace-scoped Role, and that ClusterRole grants broad read access (a common shortcut so a migration job “just works” without anyone fiddling with permissions), then the token sitting in that pod’s filesystem can read Secrets in every namespace in the cluster, not just its own.

Ledger’s migration agent runs exactly this way: a service account scoped to deploy anything in the cluster, because migrations sometimes need broad access and nobody went back and scoped it down once the migration was live. An attacker doesn’t need to escalate privileges at all. One prompt injection, one poisoned tool response that gets the agent to read and exfiltrate its own mounted token, reaches every Secret in the cluster. And from the API server’s point of view, it’s a completely normal, authenticated request. No error, no alert, nothing looks wrong. This is the Sysdig kill chain’s actual shape: the privilege was already sitting there, mounted, waiting.

The fix is three changes, in order of how cheap they are to make:

  • automountServiceAccountToken: false. The single highest-leverage setting here. If the token was never mounted, there’s nothing on disk for a compromised process to read in the first place. Most teams have simply never touched this default.
  • Namespace-scoped Role/RoleBinding instead of ClusterRole/ClusterRoleBinding. Even if a token does leak, its reach stops at the namespace boundary instead of the whole cluster.
  • Just-in-time (JIT) credential provisioning. Instead of one long-lived token valid for the pod’s entire life, the agent requests a short-lived, task-scoped credential right when it needs one. Steal that, and it’s either already expired or too narrow in scope to matter by the time anyone could reuse it.

If you’re wondering whether this is just normal Kubernetes security: yes, and that’s the point. Every one of these fixes is standard, pre-existing practice, none of it is new technology. What’s new is the stakes. A stateless service with slightly-too-broad RBAC is a bounded problem. An agent with slightly-too-broad RBAC and a live decision-making loop can chain that access into things nobody anticipated, the way one vulnerable notebook led to Docker-socket enumeration, led to host escape, led to token replay, led to a full Secret dump. No single misconfiguration in that chain would have caused the outcome alone.

Layer 2: Tools and MCP servers

Before agentic tooling, the code connecting a service to its dependencies was either a library (no separate attack surface) or a deliberately-deployed microservice that got hardened as a matter of course, because everyone treated it as a “real service.” An in-cluster MCP server sits in an awkward middle ground. It’s a real pod, with real network reach and a real service account, but teams often treat it like glue code: deployed fast, in the default namespace, on a shared service account, because the demo just needs it to work. It ends up with more trust than anyone consciously decided to give it.

Ledger’s agent runs its schema migrations through exactly that kind of MCP server: default namespace, shared service account, no restriction on what it’s allowed to reach. If that server is compromised, or if a malformed or malicious tool call reaches it and nothing validates the call’s shape before acting on it, the attacker doesn’t have a broken tool anymore. They have a new pod inside the cluster, with real network reach. That’s a foothold, not a contained failure, and it’s exactly the kind of pivot that container-based lateral movement research has been describing for a while. I’ll flag one number here honestly rather than dress it up: it’s widely cited in industry writeups that container-based lateral movement rose by roughly a third in 2025, but I was not able to trace that figure back to a single named, credible primary study, so treat it as a directional signal from the security community, not a precise, citable statistic. The point that does hold regardless of the exact number: attackers already know how to move pod to pod inside a cluster. An autonomous agent doesn’t need to discover that path. If it’s compromised, it’s already standing on it, holding a credential.

The fix is treating every MCP server as its own trust boundary, the same way you’d treat any service you didn’t fully trust yet:

  • Its own namespace, so it doesn’t get network reach to everything else by default. Network policy can then explicitly allow only what’s needed, instead of everything being reachable by default.
  • A dedicated service account, not shared with other pods, so a compromise doesn’t inherit permissions that were never meant for it.
  • A restricted Pod Security Admission profile. Even if code execution is achieved inside the MCP server’s container, restricted blocks privilege escalation, root execution, and host access, sharply narrowing what that foothold can actually do.
  • Schema validation on every tool call. The cheapest control on this list. It catches a malformed or malicious call, the wrong shape, an injected instruction disguised as a parameter, before it ever reaches the actual migration logic behind the tool.

Is this specific to MCP, or true of any microservice? It’s true of any microservice. The difference is that MCP servers are being deployed right now with an “it’s just internal tooling” casualness that a deliberately-designed service usually doesn’t get, while holding the exact same tool-execution authority a hardened service would.

Layer 3: Runtime and observability

Typical dashboards watch for a service being unhealthy: crash loops, high error rates, missing heartbeats. A compromised agent, mid-attack, usually doesn’t look unhealthy by any of those measures. It looks like a slightly more active, still-successfully-responding service: a few more API calls, maybe a few more pods, a bit more CPU. Nothing crashes. Nothing errors. By Sysdig’s own account, the cluster in the May incident looked quiet right up until the token replay and the dump, because nothing was watching for the shape of an agent going wrong, only the shape of a service going down.1

Ledger’s story is the same: the first sign its agent is compromised is a spike in API calls, pod creation, or inter-pod traffic, not an alert firing, because nobody built the alert. You don’t need a full, purpose-built agentic-security platform to close that gap. Three tripwires, wired to actually page a human, catch most of a Sysdig-style kill chain before the exfiltration step completes, because every step in that chain leaves one of these traces:

  • Audit-log alerting on token-reuse patterns. The same service-account token suddenly making requests it’s never made before, or a burst of requests inconsistent with the agent’s normal task cadence, is a detectable signature even without knowing the exact attack in advance.
  • Pod-creation-rate alerting. A compromised agent enumerating or replicating itself shows up as an unusual spike in how fast new pods are being created, a signal that has nothing to do with CPU or memory.
  • Resource-consumption canaries. A baseline of “normal” resource use for this specific agent’s normal task, with alerting on deviation, catches behavior that’s anomalous for that workload even if it looks unremarkable in isolation.

On thresholds: baseline each agent against its own normal task pattern, not a generic cluster-wide number, and tune from there. If the migration agent normally makes fifty API calls an hour, alert meaningfully above that. It’s standard anomaly-detection practice. The novelty is only in pointing it at agent-specific signals, token reuse and spawn rate, rather than only generic pod health.

Closing the loop

None of the three fixes above are new technology. That’s deliberate, and it’s also the uncomfortable part: the tools to stop a Sysdig-style incident already existed before the incident happened. What changed is that the CNCF now treats this as first-class rather than optional. Its March 2026 agentic-standards post lays out recommended patterns for running agentic workloads on cloud-native infrastructure, JIT credential provisioning among them, built around the idea that an agent should request access only when it needs it and lose that access when it’s done.2 To be precise about what that document actually is: it’s CNCF publishing recommended practice and building industry consensus, explicitly describing itself as a foundational checklist that will keep evolving, not a certification or a compliance mandate. But it does mean the pattern now has a name and a citable source, instead of being something individual teams reinvent, or skip, on their own.

Four things to leave with, one per layer plus the frame that holds them together:

  1. The Agent Blast Radius, the frame itself: permissions, tools, and runtime are the three places a compromised agent’s authority actually goes.
  2. Least-Privilege Baseline: automountServiceAccountToken: false, namespace-scoped Roles instead of ClusterRoles, and JIT credentials, the minimal starting point for any agent pod.
  3. Hardened MCP: its own namespace, its own service account, a restricted Pod Security Admission profile, and schema validation on every call.
  4. Runtime Tripwires: audit-log alerts on token reuse, pod-creation-rate alerts, and resource-consumption canaries, tuned to each agent’s own baseline.

Every one of these lives in the cluster’s own configuration, not in a smarter model or a better prompt. Take whatever agent pod you’re running right now and run it through these three layers. You’ll find the gap before the next incident report writes it up for you.

Adapted from my talk at Cloud Native Dallas, “An AI Agent Already Escaped Kubernetes. Is Your Cluster Next?” Questions or corrections welcome, reach out.

Footnotes

  1. Sysdig Threat Research, “Agentic threat actor hits the orchestration plane: AI agent-driven container escape” (published June 2026, documenting an incident observed May 29, 2026). sysdig.com. 2 3

  2. CNCF, “Cloud native agentic standards” (March 23, 2026). cncf.io.

Cite this

Khan, M. (September 17, 2026). An AI Agent Already Escaped Kubernetes. Is Your Cluster Next?. Moeez Khan. https://moeezkhan.com/writing/the-agent-blast-radius/

Moeez Khan
Moeez Khan

Software Engineer at AWS Transform, building agentic AI for enterprise and mainframe modernization — and writing about making legacy tractable at scale.

← More writing