Any AI agent that can write and run code is executing untrusted instructions, because the code it produces can be steered by prompt injection, poisoned data or a plain model mistake. A code interpreter, a shell tool or a coding agent turns a language model into a general purpose computer, and the only reliable limit on what that computer can do is the isolation boundary around it. This guide explains how to choose and configure that boundary: the isolation technologies (processes, containers, user space kernels, microVMs and WebAssembly), filesystem and network controls, credentials inside the sandbox, resource limits, monitoring and a phased rollout. It is written for platform engineers, AppSec teams and owners of agent platforms who need agents to run code without putting hosts, secrets or production systems at risk. Securing the coding workflow itself is covered in the AI Coding Agents Security Guide, and tool permissions in the AI Agent Tool and Plugin Security Guide.
Key takeaways
- Treat generated code as hostile. Whatever the model writes can be shaped by input it read, so run it as you would run code from an unknown source, never in the agent's own process or on a developer's host session.
- Match the boundary to the risk. Plain containers share the host kernel; a user space kernel such as gVisor or a microVM such as Firecracker adds a second boundary and is the right default for multi-tenant or internet-facing agents.
- Filesystem and network isolation are both required. Filesystem limits without egress control still allow exfiltration, and egress control without filesystem limits still allows code to plant persistence that later runs outside the sandbox.
- The credential is the real blast radius. A perfect sandbox does not help if the agent is handed a production token; inject short-lived, narrowly scoped credentials or none at all.
- Ephemeral, observable and limited. Create a fresh sandbox per task, destroy it afterwards, log every execution and cap CPU, memory, time and network so a runaway or abused agent fails safely.
Why agent code execution needs its own boundary
Traditional application security assumes the code is written by the organisation and reviewed before it runs. Agent code execution breaks that assumption: the code is written at run time by a model whose behaviour depends on everything in its context window, including web pages, documents, tool results and messages from other agents. OWASP's LLM06:2025 Excessive Agency entry describes exactly this risk with the example of an extension meant to run one specific shell command that fails to prevent other commands from being executed, and LLM05:2025 Improper Output Handling covers model output passed to interpreters without checks. An early, concrete case is CVE-2023-29374, where NVD records that LangChain's LLMMathChain allowed prompt injection to execute arbitrary code through Python exec (CVSS 3.1 9.8).
- Who controls the code: anyone who can put text in front of the agent. That includes a malicious issue comment, a poisoned README or a crafted error message. See the Prompt Injection Guide.
- What the code can reach: by default, everything the host process can reach: environment variables, cloud metadata endpoints, mounted credentials, the local network and the internet.
- How fast it acts: an agent loop can write, run and retry code many times per minute, so a mistake becomes a sequence of actions before a human notices.
The sandbox is therefore not an optional hardening step but the control that decides the worst case. The OpenAI and Hugging Face breach 2026 shows what happens when agents escape an evaluation sandbox and reach cloud credentials: the impact came from what the escaped code could touch, not from the model itself.
Isolation technologies compared
The options differ mainly in how much of the host kernel the untrusted code can talk to. Every layer below a shared kernel is a single bug away from host access; adding an independent second boundary is what makes an escape materially harder.
| Approach | How it isolates | Strength | Trade-offs | Typical fit |
|---|---|---|---|---|
| In-process "restricted" interpreter | Removes modules and built-ins from Python or JavaScript | Weak: language level filters are routinely bypassed | No real boundary; no library installs | Not recommended for untrusted code |
| OS process sandbox (Seatbelt, bubblewrap, Landlock, seccomp) | Kernel features restrict one process tree's filesystem, network and syscalls | Moderate; shares host kernel | Fast, no daemon; per-platform configuration | Local coding agents on developer machines |
| Standard container (runc with namespaces, cgroups, seccomp) | Namespaces and cgroups; Docker's default seccomp profile disables around 44 of 300+ syscalls | Moderate; shared kernel | Mature tooling; misconfiguration (privileged, host mounts) removes most protection | Single-tenant internal agents with trusted inputs |
User space kernel (gVisor runsc) | The Sentry implements Linux syscalls itself and does not pass them to the host; the Gofer mediates file access | Strong: two boundaries | Not every syscall or /proc file implemented; syscall heavy workloads slower | Hosted code interpreters, multi-tenant agent platforms |
| MicroVM (Firecracker, Kata Containers) | Hardware virtualisation with a minimal device model and a separate guest kernel | Strong: hypervisor boundary | Needs KVM; boot and memory overhead; image management | Untrusted public input, high-value hosts, evaluation environments |
| WebAssembly runtime (Wasmtime with WASI) | Bounds-checked linear memory; no system calls, only host-provided imports | Strong for supported workloads | Limited language and library support; no arbitrary binaries | Plugin logic, data transforms, narrow tool functions |
| Separate host or remote sandbox service | Code runs on infrastructure with no route to production | Depends on the service's own isolation | Data leaves your boundary; third-party risk | Teams without capacity to run isolation themselves |
What the primary documentation says
- gVisor: the project describes itself as an application kernel written in Go. Each sandbox gets its own Sentry, which runs under a restrictive seccomp filter with no direct filesystem access, and the Gofer serves files over 9P. Its documentation is explicit that compatibility and per-syscall performance are the costs.
- Firecracker: the design document treats every guest vCPU thread as potentially running malicious code. The
jailersets up cgroups and a chroot, then drops privileges before the VMM starts; per-thread seccomp filters load before guest code runs; the guest sees only VirtIO network and block devices, a serial console and a minimal keyboard controller. The design also states that Firecracker does no network filtering, so egress must be filtered on the host. - Wasmtime: isolation comes from bounds-checked linear memory and capability-based WASI, plus defence in depth such as 2 GB guard regions and zeroing memory after use.
- Landlock: the Linux kernel documentation describes it as letting any process, including unprivileged ones, restrict itself. Rules cover filesystem rights and, from ABI v4, TCP bind and connect by port, and once applied they can only be tightened.
In Kubernetes, a RuntimeClass (stable since v1.20) lets agent execution pods select a hardened runtime such as gVisor or a VM-backed runtime while ordinary workloads keep the default. See the Container Security Guide and the Kubernetes Security Guide.
Choosing a sandbox model
| Situation | Minimum isolation | Why |
|---|---|---|
| Developer runs a coding agent locally on own repository | OS process sandbox with write limits and an egress allowlist | The main risks are credential reads, persistence in shell profiles and exfiltration |
| Internal agent, trusted users, internal data only | Hardened container: non-root, all capabilities dropped, read-only root filesystem, default seccomp, no host mounts | Inputs are mostly trusted but indirect injection is still possible |
| Agent reads internet content, email or tickets from outsiders | gVisor or microVM, per-task sandbox, deny-by-default egress | Attackers control part of the context, so expect hostile code |
| Multi-tenant platform executing customers' agent code | MicroVM or gVisor per tenant and per session, separate node pools | A kernel escape would cross tenant boundaries |
| Model evaluation, red teaming or capability testing | MicroVM on isolated accounts with no production credentials and full logging | The point of the test is to find behaviour you did not expect |
- Small organisations: start with a hardened container or a managed sandbox service and put the effort into credentials and egress, which matter more than the runtime choice at small scale.
- Large organisations and platforms: standardise one hardened execution runtime, expose it as an internal service with a single API, and stop teams building ad hoc
exectools inside agent processes. - Remote sandbox services: evaluate where the data goes, how sessions are isolated from other customers, how long files persist and how the API key for the service is scoped. That key is itself a privileged NHI.
Filesystem, network and syscall controls
Choosing a runtime is half the work. The configuration inside it decides what an escaped or misbehaving agent can do.
Filesystem
- Write scope: allow writes only to a per-task working directory and a temp directory. Claude Code's sandbox documentation, for example, notes that writable directories on
$PATHor shell configuration files let code run later in other contexts, and keeps paths such as.git/hooksand its own settings write-denied even inside the project. - Read scope: reads are often broad by default. The same documentation states that credential files such as
~/.sshand~/.aws/credentialsare readable unless denied, so add explicit deny rules for home directories and credential stores. - Mounts: never mount the container runtime socket into an agent sandbox. Mounting
/var/run/docker.sockis equivalent to host root, and Claude Code's documentation lists allowing such a socket as effectively granting host access. AutoGen's documentation suggests mounting the socket into the application container for Docker-out-of-Docker, which gives that container control of the host's Docker daemon. CrewAI's former Docker execution mode mounted the current working directory, which exposes whatever sensitive files sit there. - Root filesystem: read-only, with a small writable
emptyDiror tmpfs for work.
Network
- Default deny: no outbound traffic unless the task needs it, then an allowlist of hostnames enforced by a proxy outside the sandbox.
- Know the proxy's limits: a hostname allowlist without TLS inspection decides on the requested name, and broad domains such as a code hosting site can still carry exfiltrated data. Allow specific paths or use a TLS-inspecting egress proxy for high-risk agents.
- Block metadata and internal ranges: deny the cloud instance metadata address (169.254.169.254) and private ranges from execution sandboxes so code cannot pick up the host's cloud role. See the Zero Trust for AI Agents Guide.
- Non-HTTP protocols: raw TCP, UDP and DNS tunnelling bypass HTTP proxies; run the sandbox in its own network namespace so the proxy is the only route.
Syscalls and privileges
- Seccomp: keep at least the runtime default profile. Docker's default blocks calls such as
bpf,mount,kexec_load,init_module,perf_event_openand theio_uringfamily; never run agent code withseccomp=unconfined. - Kubernetes settings: apply the Pod Security Standards Restricted profile to execution namespaces:
runAsNonRoot: true,allowPrivilegeEscalation: false,capabilities.drop: ["ALL"],seccompProfile.type: RuntimeDefault, and nohostPath,hostNetworkorhostPID. - Fail closed: some tools fall back to running unsandboxed when the sandbox cannot start. Claude Code, for instance, offers
failIfUnavailableto stop that fallback. Check the equivalent setting in any framework you use.
Credentials and identity inside the sandbox
Most real damage from agent code execution comes from the credentials it can use, not from kernel escapes. The sandbox should hold as little identity as possible.
- No ambient secrets: strip environment variables, credential files and token caches from the image and the working directory before the agent's code runs. Scan images for secrets as part of the build.
- Scoped, short-lived tokens: where code needs to call an API, inject a token scoped to that task and that resource, with a lifetime of minutes. LangChain's own security policy says to assume the model may misuse any access it has: if a credential can delete data, an agent holding it can delete data. The PocketOS database deletion 2026 is the example: an over-privileged platform token, not a sandbox flaw, let a coding agent wipe production.
- Broker instead of hand over: where possible, keep credentials outside the sandbox and let a broker or tool gateway make the privileged call on the code's behalf, with policy checks.
- Distinct workload identity: give the execution environment its own identity, separate from the agent orchestrator and from the human who started it, so logs and revocation work per sandbox. See the AI Agent Authorisation Guide and the Secrets Management Guide.
Resource limits and lifecycle
| Control | Typical setting | Risk it limits |
|---|---|---|
| Wall clock timeout per execution | Seconds to a few minutes, task dependent | Runaway loops, crypto mining, slow exfiltration |
| CPU and memory limits (cgroups) | Fixed quota per sandbox | Denial of service to neighbours; OWASP LLM10 Unbounded Consumption |
| Process count limit (pids) | Low ceiling | Fork bombs |
| Disk quota on writable layer | Small, per task | Disk exhaustion, staging large data |
| Network rate limits | Bandwidth and operation caps (Firecracker supports token bucket limiters per interface) | Bulk exfiltration |
| Session lifetime | One sandbox per task or conversation, destroyed afterwards | Persistence, cross-task data leakage |
| Image provenance | Pinned, signed base images; approved package mirrors | Supply chain compromise through dependencies the agent installs |
Agents often install packages to finish a task. Route installs through an internal mirror with an allowlist so a hallucinated or typosquatted package name cannot pull in malware. See the Software Supply Chain Security Guide.
Detection and measurement
Log at the boundary, not only in the agent. The agent's own transcript can be manipulated; the runtime's records cannot.
- Execution records: the code submitted, the sandbox ID, the initiating agent and user, start and end time, exit status and resource usage.
- Egress logs: every allowed and denied destination from the proxy. Denied requests to metadata addresses or unknown domains are high-value signals.
- Runtime alerts: seccomp denials, attempts to access the runtime socket, unexpected process trees and writes outside the working directory.
- Credential use: any use of a sandbox-issued token from an address outside the sandbox network is a likely leak.
Metrics
- Percentage of agent code execution paths running in an approved sandbox runtime (target 100 percent; any in-process
exectool is a finding). - Percentage of execution sandboxes with deny-by-default egress.
- Number of long-lived or production credentials found inside sandbox images or environments (target zero).
- Median sandbox lifetime, showing whether sandboxes really are ephemeral.
- Count of blocked egress and seccomp events per thousand executions, trended over time.
- Time from a sandbox alert to revocation of its credentials. See the AI Agent Kill Switch and Containment Guide.
Phased rollout
- Inventory: find every agent and tool that can run code, including code interpreter tools, shell tools, notebook kernels and coding agents on developer machines. Note where each one runs and which credentials it can see.
- Remove the worst paths first: disable any tool that executes code in the agent's own process or directly on a host, such as framework "local" or "unsafe" executors.
- Stand up a standard runtime: a hardened container profile for low-risk use and gVisor or microVMs for agents that see external input. Publish it as a shared service.
- Pilot in audit mode: run one team's agents in the new sandbox with egress logging but a permissive allowlist for two to four weeks, collecting which domains, packages and files tasks actually need.
- Enforce: switch egress to deny by default using the observed allowlist, enable fail-closed behaviour, and move credentials to brokered or short-lived injection.
- Test: include sandbox boundary tests in agent security testing, for example confirming that metadata endpoints, the runtime socket and home directories are unreachable. See the AI Agent Security Testing Checklist.
- Roll back safely: if enforcement breaks tasks, widen the specific allowlist entry or resource limit for that agent rather than disabling the sandbox; keep the previous configuration versioned so it can be restored in minutes.
Common failure patterns
- Language level "sandboxes": relying on a restricted Python environment or blocked keyword lists inside the agent process. These are filters, not boundaries.
- The runtime socket mount: mounting the Docker socket so the agent can start containers, which hands host control to whatever code the agent writes.
- Credentials riding along: sandboxes inheriting the host's environment variables, cloud role or a developer's token cache, so isolation of the code does not isolate the identity. PocketOS illustrates the cost.
- Open egress: a strong runtime with unrestricted internet access, which lets injected code send data anywhere and fetch further tooling.
- Silent fallback: the sandbox fails to start on one platform and the tool runs commands unsandboxed without anyone noticing.
- Long-lived shared sandboxes: one environment reused across users or tasks, so data and planted files carry from one session to the next.
Lessons from incidents
- The OpenAI and Hugging Face breach 2026 shows that evaluation sandboxes need the same rigour as production: escaped agents went straight for cloud credentials, so the sandbox network and identity scope set the impact.
- The PocketOS database deletion 2026 shows that the token handed to an agent defines the worst case regardless of where its code runs.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST SP 800-53 Rev. 5 | SC-39 Process Isolation; SC-44 Detonation Chambers; SC-7 Boundary Protection; AC-6 Least Privilege; CM-7 Least Functionality; AU-12 Audit Record Generation; SI-4 System Monitoring | Isolated execution domains, egress control, minimal tools and credentials, logging |
| NIST CSF 2.0 | PR.AA-05; PR.PS-01; PR.IR-01; DE.CM-09 | Least privilege access, configuration management, environment protection, runtime monitoring |
| OWASP Top 10 for LLM Applications 2025 | LLM05 Improper Output Handling; LLM06 Excessive Agency; LLM10 Unbounded Consumption | Model output reaching interpreters, over-broad tools, resource abuse |
| MITRE ATLAS | AML.T0051 LLM Prompt Injection; AML.T0053 AI Agent Tool Invocation; AML.T0050 Command and Scripting Interpreter | How agent code execution is abused |
| MITRE ATT&CK v20 | T1059.006 Python; T1611 Escape to Host; T1552.001 Credentials In Files; T1567 Exfiltration Over Web Service | Behaviours to detect at the sandbox boundary |
| MITRE D3FEND | D3-EI Execution Isolation; D3-KBPI Kernel-based Process Isolation; D3-HBPI Hardware-based Process Isolation; D3-NI Network Isolation | Defensive techniques the sandbox implements |
Practitioner checklist
- List every agent tool that executes code and where that code actually runs.
- Remove in-process and host "local" executors from production agents.
- Use gVisor or a microVM for any agent that processes external content or serves multiple tenants.
- Apply non-root, drop all capabilities, read-only root filesystem and the runtime default seccomp profile to every execution sandbox.
- Never mount the container runtime socket or host credential paths into a sandbox.
- Enforce deny-by-default egress through a proxy outside the sandbox, and block metadata and internal address ranges.
- Keep production credentials out of sandboxes; use brokered calls or short-lived, task-scoped tokens.
- Create one sandbox per task, cap CPU, memory, processes, disk and time, and destroy it afterwards.
- Configure tools to fail closed when the sandbox cannot start.
- Log executions, egress and runtime denials at the boundary and alert on credential use from outside the sandbox.
Standards and references
- NIST: SP 800-53 Rev. 5 Security and Privacy Controls
- NIST: SP 800-190 Application Container Security Guide
- OWASP: Top 10 for LLM Applications 2025
- MITRE D3FEND: Execution Isolation
- gVisor: What is gVisor
- Firecracker: Design
- Linux kernel documentation: Landlock unprivileged access control
- Docker: Seccomp security profiles for Docker
Related NHI Mgmt Group resources: AI Coding Agents Security Guide · AI Agent Tool and Plugin Security Guide · Multi-Agent and A2A Security Guide · Browser and Computer-Use Agent Guide · Securing Agent Frameworks Guide