Ask most teams how they secure an agent that writes and runs code, and the answer is "it runs in a sandbox". Ask what the sandbox stops, and the answers get vaguer. AI agent sandboxing is treated as a binary property — either you have one or you do not — when it is really a set of four independent boundaries, each of which has to be drawn deliberately.
The framing of "sandbox escape" does not help. It suggests the risk is an attacker defeating the isolation layer through some kernel exploit. That happens, and it is rare. Far more often nothing is escaped at all: the agent simply reaches something that was inside the perimeter the whole time.
gVisor's own documentation puts the point better than most security vendors will: "A sandbox is not a substitute for a secure architecture."
The quick answer
A sandbox constrains what code can do to the host: which syscalls it can make, which files it can read, which hosts it can reach, and which credentials are available to it. Most real agent incidents are failures of the last two rather than the first two. Isolation technology has improved considerably; credential scope and network egress are where the gaps remain, because those are configuration decisions rather than properties of the runtime you chose.
Key takeaways
- A sandbox is four boundaries — syscall, filesystem, network and credential — and teams routinely draw two of them.
- Instructions are not a boundary. Red-teaming research finds that roughly one in five confirmed agent safety violations happens after the agent has stated the constraint it then breaks.
- Prompt injection against long-horizon agents reaches 96.7% success undefended and 69.2% against a common safety filter, so containment has to carry the load that filtering cannot.
- Egress control is the highest-leverage boundary: exfiltration needs a socket, not an exploit.
- Credentials inside the sandbox are the most common real-world failure, and the least discussed.
- Stronger isolation costs real performance, and choosing it is a threat-model decision, not a default.
What a sandbox actually does
Sandboxes work by interposing on the interface between untrusted code and the host kernel. The Linux kernel is a very large API — hundreds of syscalls, each with its own history — and most sandbox escapes historically came from bugs in that surface.
gVisor is explicit about attacking exactly this problem: its "primary design goal is to minimize the System API attack vector through multiple layers of defense, while still providing a process model". It does that by putting a userspace kernel — the Sentry — in the path, so that "the application's direct interactions with the host System API are intercepted by the Sentry, which implements the System API instead".
It is equally explicit about limits. gVisor "does not provide protection against hardware side channels, although it may make exploits ... more difficult to use", and it relies on the host and platform for defence against hardware-based attacks. That candour is worth imitating in your own threat model: name what the layer does not cover, so nobody assumes it does.
The four boundaries
It helps to stop asking "are we sandboxed?" and start asking four separate questions.
| Boundary | The question | Typical failure |
|---|---|---|
| Syscall / kernel | What can this process ask the kernel to do? | Default container profile, shared kernel, no seccomp filter |
| Filesystem | What can it read and write? | Source tree mounted read-write; .env and SSH keys inside the mount |
| Network egress | What can it connect to? | Unrestricted outbound; the default in nearly every runtime |
| Credentials | What can it authenticate as? | Long-lived tokens in the environment, scoped to a whole account |
The first two get attention because they are what "sandbox" connotes. The second two decide what an incident costs, and they are properties of how you configured the environment rather than of which isolation technology you picked.
There is a fifth constraint that sits slightly apart: resource consumption. The 2025 OWASP Top 10 for LLM Applications lists Unbounded Consumption as LLM10, and it is the boundary teams discover through a bill rather than a breach. An agent in a retry loop can burn CPU, disk and API spend without ever doing anything a security review would flag as malicious. Wall-clock timeouts, memory and disk quotas, and a hard cap on tool-call depth belong in the sandbox definition alongside the security boundaries, because the runtime is the only place that can enforce them.
Mapping the boundaries onto that OWASP list is a useful exercise in itself: prompt injection (LLM01) is how the agent is turned, excessive agency (LLM06) is what it can then reach, improper output handling (LLM05) is what happens when its output is trusted downstream, and unbounded consumption (LLM10) is what it costs while doing so. A sandbox is the enforcement point for the middle two and the last one. It does nothing at all about the first, which is exactly why the containment argument matters.
Why instructions are not a boundary
The most common substitute for a real boundary is a rule in the system prompt: do not read files outside the working directory, do not call external services, ask before deleting anything. This fails in a way that is now well measured, and the measurement is more damning than the intuition.
REDAgentBench, published in August 2026, runs 1,661 executable red-teaming cases across five service surfaces, six models and three agent harnesses, and verifies harm "from service receipts and final-state changes" rather than from what the transcript appears to say. Macro-average attack success rate: 65.69%.
The finding that should change how you build is narrower. In their diagnostic cohort, "almost one in five confirmed violations with resolved action anchors occurs after the agent states the relevant constraint or risk, revealing a Recognition--Execution Gap".
The model knew the rule, said the rule, and then broke it. A control that depends on the model choosing to comply is not a control.
The same paper offers a genuinely useful counterweight: a "training-free policy reminder reduces confirmed violations by more than 70 percentage points in matched replay". That is a large effect for a cheap intervention, and it is worth deploying. It is still mitigation rather than containment, and the distinction matters when you are deciding what to rely on.
Injection pressure is meanwhile getting worse, not better. ECLIPSE, a self-evolving prompt-injection framework aimed specifically at long-horizon agentic systems, reports "96.7% attack success without defense and 69.2% under the common safety filter, exceeding the strongest baseline by 27.5% in the defended setting". If a filter leaves roughly two-thirds of attacks succeeding, the architecture behind it is doing the actual work. This is the same structural argument as in why prompt injection cannot be filtered away: containment scales where detection does not.
Choosing an isolation strength
Stronger isolation is available and it is not free. The honest framing is a trade, not a ranking.
| Approach | Kernel boundary | Reasonable for |
|---|---|---|
| Process + seccomp | Shared host kernel, filtered syscalls | Trusted code, defence in depth |
| Container (namespaces, cgroups) | Shared host kernel | Multi-tenant workloads you wrote |
| gVisor-style userspace kernel | Intercepted; small host surface | Running code an LLM produced |
| microVM | Separate guest kernel, hardware virtualisation | Untrusted code, multi-tenant |
| Separate host or account | Physical or account boundary | Blast-radius control for high-value data |
For an agent executing code it generated from untrusted input, a shared-kernel container is the weakest thing that still deserves the name. Anything at or above gVisor is a reasonable default. But notice that the whole table concerns only the first of the four boundaries — you can choose the strongest row and still hand the agent a production database credential.
The credential problem
This is the boundary that produces the incidents that actually hurt, and it gets the least engineering attention because it is not exciting.
The pattern is consistent. The sandbox is built carefully. Then the agent needs to call an internal API, so a token goes into the environment. The token is long-lived because rotation is inconvenient, and broadly scoped because scoping it properly means understanding which permissions the agent actually needs. Now the isolation boundary is real and irrelevant: an attacker who influences the agent does not need to escape anything, because the credential inside the sandbox already reaches what they want.
OWASP names this directly in LLM06:2025, Excessive Agency — "the vulnerability that enables damaging actions to be performed in response to unexpected, ambiguous or manipulated outputs from an LLM" — and attributes it to excessive functionality, excessive permissions and excessive autonomy. Its mitigations are unglamorous and correct: "Limit the permissions that LLM extensions are granted to other systems to the minimum necessary", "Require a human to approve high-impact actions before they are taken", and — the one most often skipped — "Implement authorization in downstream systems rather than relying on an LLM".
That last point is the whole design principle compressed into a sentence. If the downstream service enforces what the caller may do, an agent that goes wrong hits a wall it cannot argue with. If enforcement lives in the agent's instructions, it hits a suggestion.
Practically: short-lived credentials, minted per task, scoped to the specific resources that task needs, with the authorisation decision made by the resource rather than the caller. UniverseBlend's survey of the gaps in agent skill registries is a good companion here, because third-party skills are how over-broad permissions usually enter a system.
Egress is the boundary that pays
If you only harden one thing, harden outbound network access.
Almost every serious agent incident ends the same way: data leaves. Whether the trigger was injection, a hallucinated tool call or a genuine bug, the damage is done at the point where something crosses the network to somewhere it should not. Exfiltration needs a socket, not an escape — and unlike kernel hardening, egress control does not require you to anticipate the attack.
The workable pattern is deny-by-default outbound, with an allowlist of specific hosts reached through a proxy that logs. This is more restrictive than most teams expect to tolerate and less disruptive than they fear, because the set of hosts a given agent legitimately needs is usually small and enumerable. UniverseBlend has a thorough walkthrough of the paths data can take out of an agent, including the ones that are not obviously network calls.
Log the content the model read, not only the actions it took. Systems that record actions alone produce incidents nobody can reconstruct afterwards, which is a problem for your own engineers before it is a problem for any regulator — though under the EU AI Act's deployer obligations the retention question acquires a second deadline. UniverseBlend's guide to what to do when the log lies is worth reading before you need it.
What to actually build
A defensible baseline for an agent that executes model-generated code:
- Kernel boundary at gVisor strength or above. Shared-kernel containers are not sufficient for code an LLM wrote from untrusted input.
- Read-only by default on everything except an explicit scratch directory, and keep secrets out of the mounted tree entirely rather than relying on ignore rules.
- Deny outbound, allowlist through a logging proxy. The single highest-leverage control.
- Per-task, short-lived, narrowly scoped credentials, with authorisation enforced downstream.
- Human approval on high-impact actions, defined by the effect rather than the tool name.
- Log inputs as well as actions, with enough fidelity to reconstruct why the agent did what it did.
- Policy reminders in-context, since they measurably help — as mitigation layered on containment, never as a substitute for it.
What this means going forward
The research direction worth watching is the shift from measuring whether an attack produced a bad-looking transcript to verifying whether it produced a bad outcome. REDAgentBench's insistence on confirming harm from "service receipts and final-state changes" is a methodological correction with a practical consequence: evaluations that scored transcripts have been measuring something other than safety, and numbers from the two approaches are not comparable.
The second shift is architectural. As agents run longer and chain more tool calls, the attack surface stops being the prompt and becomes the trajectory. Defences that inspect a single input do not see an intent distributed across twenty steps. That pushes the useful controls further down the stack — into what the process can reach, not what the text appears to say — which is the same conclusion the sandboxing literature reached, arrived at from the other direction.
Frequently asked questions
Is a Docker container enough to sandbox an AI agent?
For code you wrote, usually. For code a model generated in response to untrusted input, no. Standard containers share the host kernel, so the entire syscall surface remains reachable and a kernel bug is a host compromise. Use a userspace-kernel runtime such as gVisor or a microVM, and treat the container boundary as one layer rather than the boundary.
What is the difference between a sandbox escape and a sandbox failure?
An escape defeats the isolation layer, typically through a kernel or hypervisor bug. A failure is when the agent reaches something harmful without leaving the sandbox at all — a mounted secret, an over-scoped token, an unrestricted network. Escapes are rare and get the headlines; failures are common and cause most real damage.
Do system prompt rules stop an agent from misbehaving?
They help and they do not suffice. Measured red-teaming finds that close to one in five confirmed violations occurs after the agent has explicitly stated the constraint it goes on to break. Policy reminders reduce violations substantially — more than 70 percentage points in one replay experiment — which makes them worth deploying as mitigation, not as the boundary you rely on.
Why is network egress more important than filesystem isolation?
Because reading a secret is only half an attack. Data the agent reads but cannot transmit is contained; data it transmits is gone irreversibly. Egress control also fails safe against attacks you did not anticipate, since novel exfiltration paths still need an outbound connection to somewhere.
How do we scope credentials for an agent that needs broad access?
Usually the requirement is narrower than stated. Decompose the task: most agents need a few specific operations on a few specific resources, not account-level access. Mint per-task tokens with those scopes, keep lifetimes in minutes, and put the authorisation check in the downstream service so the agent cannot talk its way past it.
Final takeaway
The sandbox question that matters is not which isolation technology you chose. It is what an attacker who fully controls the agent's behaviour could reach without defeating anything — which files are mounted, which hosts are reachable, which credentials are present.
Answer that honestly and the work usually turns out to be unglamorous: scope the tokens, deny the egress, move the authorisation downstream, log what the model read. None of it requires anticipating a specific attack, which is precisely why it holds when the attack is one nobody predicted.
Sources and further reading
- gVisor security model and its stated limitations
- OWASP LLM06:2025, Excessive Agency
- OWASP LLM01:2025, Prompt Injection
- Chen et al., REDAgentBench: Executable Red Teaming and Faithful Measurement of LLM Agent Systems, arXiv 2608.10669
- Zhao et al., ECLIPSE: Self-Evolving Stealthy Prompt Injection Attack against Long-Horizon Agentic Systems, arXiv 2608.30441





