boxkite
← All posts
Security

Anatomy of an Agent Sandbox Escape: What Actually Stops rm -rf /

"The agent hallucinated and ran rm -rf /" is the scenario every security review of an agent sandbox eventually asks about. The honest answer isn't one mechanism — it's four independent ones, and the interesting part is what happens if you imagine each one failing in turn.

Start with the command that should never leave the pod

Walk through it concretely. An agent, given bash_tool access, decides — through a prompt-injection, a hallucination, or a genuinely reasonable-looking plan that goes wrong — to run rm -rf /. What actually happens next is a sequence of independent boundaries, each of which would contain the damage even if the ones before it didn't exist.

Four layers, checked in order

Non-root userno permission to touch most of the host-mapped filesystem
Every capability droppedno CAP_SYS_ADMIN, no override for anything root would need
Read-only root filesystemthe delete has nowhere writable to even attempt
Ephemeral, disposable podworst case, this exact pod is destroyed and replaced
Each box below is a separate mechanism. None of them assumes the others worked — that's the actual definition of defense in depth, not just a phrase on a slide.

Layer one: there's no root to escalate to

The sandbox process doesn't run as root inside its container. A destructive command still has to operate within whatever permissions its own non-root user actually has — which, on a correctly hardened image, is "not much outside its own workspace directory."

Layer two: capabilities are gone, not just UID

Dropping root is necessary but not sufficient by itself — Linux capabilities can grant root-equivalent power to a process that technically has a non-root UID. boxkite's sandbox containers drop every Linux capability, so there's no leftover CAP_DAC_OVERRIDE or similar sitting around that would let a clever command bypass ordinary file permission checks.

Layer three: even a privileged write attempt hits a read-only mount

The sandbox container's root filesystem is mounted read-only. Even in a scenario where the first two layers were somehow bypassed, the underlying filesystem itself refuses the write at the kernel/mount level — an independent check that doesn't depend on the process's UID or capability set being correct.

Layer four: the blast radius is one disposable pod, not your infrastructure

Every session gets its own Kubernetes pod, torn down at the end of the session (or on demand). In the genuinely worst case — every layer above fails in some way nobody anticipated — the actual damage is bounded to a pod that was always going to be destroyed anyway. It never had access to the host node's filesystem, another tenant's pod, or your production infrastructure, because it was never running alongside them in the first place.

Why "which layer stopped it" is the wrong question

A security review that asks "which one of these actually stops the attack" is asking the wrong question — the design goal is that it doesn't matter which one does, because each is independently sufficient on its own, not a chain that only works if every link holds. That's the actual test worth running: pick one layer, imagine it disabled, and check whether the sandbox is still safe. If the answer is no for every layer you try, that's a real defense-in-depth design. If disabling any single one breaks the whole model, it wasn't actually four layers — it was one layer wearing three costumes.