Hunting code-interpreter and tool sandbox escape: the model writes code and something runs it
An AI application that runs model-generated code, a code interpreter, an agent tool that shells out, a notebook
backend, is executing attacker-influenceable instructions, because the model's output is shaped by its input
and its input can be attacker-controlled. The sandbox that runs that code is therefore a security boundary
around hostile code, and it is often built as if the code were trusted. The escapes are concrete. The runtime
may have network access, so generated code reaches internal services or exfiltrates. It may see a writable host
filesystem or a shared mount, so code reads or writes outside the jail. It may carry credentials, an API key,
a cloud role, a token, in its environment, so code steals them. The isolation may be thin, a shared kernel, a
container with a host mount, a subprocess with no namespace, so a known primitive escapes it. And with no CPU,
memory, time, or output bound, one run starves the host. The hunt is to run code in the sandbox and see what of
the host it can touch. You hunt this by making the model emit probing code and observing what succeeds.
When to use
- An AI feature executes model-generated code or shell, or runs agent tools, inside a sandbox.
- The sandbox may have network access, a writable or shared filesystem, or credentials in its environment.
- Isolation may be thin (shared kernel or mount) or resource limits may be missing.
Scope check
Test sandbox escape only on AI applications and runtimes you own or are authorized to assess, in a
non-production sandbox. Running probing code exercises real execution and can reach real resources, so use an
isolated test deployment and never touch data, credentials, or hosts that are not yours. If you can't name the
authorization, stop.
The loop
Establish the intended sandbox boundary first. Name what the runtime is allowed to touch: no network or a
narrow allowlist, an ephemeral filesystem with nothing host-shared, no ambient credentials, hard CPU/memory/
time/output limits, and isolation strong enough for hostile code. This is the false-positive killer: a
runtime with no egress, no host mount, no credentials in scope, enforced resource bounds, and real isolation
is behaving correctly. Name the intended boundary, then test each edge.
Test network egress from the runtime. Have the model emit code that opens a connection: to an external
collector you control, to an internal address, and to a cloud metadata endpoint. Confirm egress is blocked or
allowlisted. A runtime with open network access lets generated code exfiltrate and pivot inside.
Test filesystem reach. Run code that lists, reads, and writes outside the working directory: the host
root, a shared mount, other users' or sessions' data, and the runtime's own configuration. Confirm the
filesystem is ephemeral and unshared. A writable or shared host filesystem lets code read secrets or persist
across the boundary.
Hunt for ambient credentials. Enumerate the environment, instance metadata, mounted service-account
tokens, and config files reachable from the runtime. Confirm no usable credential is in scope. A cloud role,
API key, or token the sandbox can read turns code execution into credential theft and lateral movement.
Test isolation strength and resource bounds. Probe the isolation: whether it is a shared kernel, a
container with a dangerous mount or capability, or a bare subprocess, and whether a known escape primitive
works. Separately, run code that spins CPU, allocates memory, sleeps, and emits huge output, and confirm each
is bounded. Thin isolation escapes to the host; missing bounds let one run starve it.
Confirm and record. Confirm by escaping the sandbox from model-driven code: reaching the network, reading
or writing the host filesystem, stealing a credential, or breaking isolation, on a non-production runtime and
without touching real resources. Kill the lead if the runtime has no egress, no host-shared or writable
filesystem, no ambient credentials, enforced resource bounds, and isolation that holds against a known
primitive. Record the model-generated code or tool argument, the host resource it reached, and the missing
isolation, credential, or resource bound.
Where the sandbox leaks
- Network access from the runtime. Egress lets generated code exfiltrate to the outside and reach internal
services and metadata endpoints.
- A writable or shared host filesystem. A host mount, a shared volume, or a writable root lets code read
secrets and persist beyond the run.
- Ambient credentials in scope. An API key, cloud role, or service-account token the runtime can read turns
execution into credential theft.
- Thin isolation. A shared kernel, a dangerous capability or mount, or a bare subprocess is escapable by a
known primitive, so the guest becomes the host.
- Missing resource bounds. No CPU, memory, time, or output limit lets one model-driven run starve or hang
the host and neighboring sessions.
Worked example (a confirm and a kill)
Confirm. A code-interpreter feature runs model-generated Python in a container that has outbound network
access and a mounted cloud service-account token. A prompt that steers the model into emitting code which
reads the token file and posts it to an external endpoint succeeds, exfiltrating a credential that grants cloud
access. Confirmed sandbox credential theft via egress and mounted token, critical, remediation = remove
ambient credentials from the runtime, block network egress by default, and mount no host secret into the
code-execution sandbox.
Kill. The runtime runs generated code with no network egress, an ephemeral filesystem with no host mount
or shared volume, no credentials or metadata reachable in its environment, hard CPU/memory/time/output limits,
and isolation that resists a known escape primitive. Probing code cannot reach the network, the host
filesystem, a credential, or the host. Killed, kill_reason = "no egress, no host-shared filesystem, no
ambient credentials, enforced resource bounds, and isolation holds; model-driven code touches nothing outside
the jail."
Rationalizations to reject
- "It only runs the user's own code." → The model's output is shaped by attacker-influenceable input; treat
everything the runtime executes as hostile and bound it accordingly.
- "It is in a container." → A container is not a sandbox by itself; confirm no host mount, no dangerous
capability, no egress, and no known escape primitive.
- "There are no secrets in there." → Enumerate the environment, metadata, and mounted tokens from inside the
runtime; ambient credentials are the most common one people forget.
- "We need network for it to be useful." → Then allowlist specific destinations; open egress lets generated
code exfiltrate and reach internal services and metadata.
- "Runs are short." → Without enforced CPU, memory, time, and output bounds a single run can still starve or
hang the host; short is not bounded.
Executing this in practice
You need the runtime's network policy, its filesystem view and any host sharing, the credentials reachable from
inside, the isolation mechanism, and the resource limits. Drive the model to emit code that probes each: an
egress beacon, a host-path read and write, a credential enumeration, and a resource-exhaustion loop. Reading the
sandbox configuration shows the intended boundary; code that reaches the network, the host, or a credential
shows whether it holds.
Related
auditing-ai-agent-permissions - the agency and approval layer above the runtime; excessive agency plus a
weak sandbox is how a tool call becomes host access.
auditing-mcp-tool-integrations - tools an agent calls are the other execution surface; their arguments reach
the same shells and paths this skill jails.
hunting-container-escape-surface - the container-isolation mechanics a code sandbox depends on; the escape
primitives are shared.
auditing-ml-inference-endpoint-abuse - the model serving that produces the code; abusing the endpoint and
escaping the runtime are the two halves of the AI-execution surface.
- FINDING-SCHEMA.md - source = the model-generated code or tool argument, sink = the
host resource it reaches, evidence = the missing isolation, credential, or resource bound.
1---2name: hunting-code-interpreter-and-tool-sandbox-escape3description: Hunt for ways attacker-influenced code or a tool call escapes the sandbox an AI application runs it in: a code-interpreter or tool runtime that executes model-generated code with network access, a writable host filesystem, or credentials it should never see, a sandbox that shares a kernel, a mount, or an environment variable with the host so the guest reaches out, a resource with no CPU, memory, time, or output bound so one run starves the host, and a tool whose arguments reach a shell or a path outside the jail. Covers AI features that run model-produced code or shell in a sandbox: code interpreters, agent tool runtimes, and notebook or eval backends. Use when a model's output becomes code that executes and the sandbox is the boundary. The model-generated code or tool argument is the source, the host resource it reaches is the sink, and the missing isolation, credential, or resource bound that lets it out is the bug.4license: MIT5---67# Hunting code-interpreter and tool sandbox escape: the model writes code and something runs it89An AI application that runs model-generated code, a code interpreter, an agent tool that shells out, a notebook10backend, is executing attacker-influenceable instructions, because the model's output is shaped by its input11and its input can be attacker-controlled. The sandbox that runs that code is therefore a security boundary12around hostile code, and it is often built as if the code were trusted. The escapes are concrete. The runtime13may have network access, so generated code reaches internal services or exfiltrates. It may see a writable host14filesystem or a shared mount, so code reads or writes outside the jail. It may carry credentials, an API key,15a cloud role, a token, in its environment, so code steals them. The isolation may be thin, a shared kernel, a16container with a host mount, a subprocess with no namespace, so a known primitive escapes it. And with no CPU,17memory, time, or output bound, one run starves the host. The hunt is to run code in the sandbox and see what of18the host it can touch. You hunt this by making the model emit probing code and observing what succeeds.1920## When to use2122- An AI feature executes model-generated code or shell, or runs agent tools, inside a sandbox.23- The sandbox may have network access, a writable or shared filesystem, or credentials in its environment.24- Isolation may be thin (shared kernel or mount) or resource limits may be missing.2526## Scope check2728Test sandbox escape only on AI applications and runtimes you own or are authorized to assess, in a29non-production sandbox. Running probing code exercises real execution and can reach real resources, so use an30isolated test deployment and never touch data, credentials, or hosts that are not yours. If you can't name the31authorization, stop.3233## The loop34351. **Establish the intended sandbox boundary first.** Name what the runtime is allowed to touch: no network or a36 narrow allowlist, an ephemeral filesystem with nothing host-shared, no ambient credentials, hard CPU/memory/37 time/output limits, and isolation strong enough for hostile code. This is the false-positive killer: a38 runtime with no egress, no host mount, no credentials in scope, enforced resource bounds, and real isolation39 is behaving correctly. Name the intended boundary, then test each edge.40412. **Test network egress from the runtime.** Have the model emit code that opens a connection: to an external42 collector you control, to an internal address, and to a cloud metadata endpoint. Confirm egress is blocked or43 allowlisted. A runtime with open network access lets generated code exfiltrate and pivot inside.44453. **Test filesystem reach.** Run code that lists, reads, and writes outside the working directory: the host46 root, a shared mount, other users' or sessions' data, and the runtime's own configuration. Confirm the47 filesystem is ephemeral and unshared. A writable or shared host filesystem lets code read secrets or persist48 across the boundary.49504. **Hunt for ambient credentials.** Enumerate the environment, instance metadata, mounted service-account51 tokens, and config files reachable from the runtime. Confirm no usable credential is in scope. A cloud role,52 API key, or token the sandbox can read turns code execution into credential theft and lateral movement.53545. **Test isolation strength and resource bounds.** Probe the isolation: whether it is a shared kernel, a55 container with a dangerous mount or capability, or a bare subprocess, and whether a known escape primitive56 works. Separately, run code that spins CPU, allocates memory, sleeps, and emits huge output, and confirm each57 is bounded. Thin isolation escapes to the host; missing bounds let one run starve it.58596. **Confirm and record.** Confirm by escaping the sandbox from model-driven code: reaching the network, reading60 or writing the host filesystem, stealing a credential, or breaking isolation, on a non-production runtime and61 without touching real resources. Kill the lead if the runtime has no egress, no host-shared or writable62 filesystem, no ambient credentials, enforced resource bounds, and isolation that holds against a known63 primitive. Record the model-generated code or tool argument, the host resource it reached, and the missing64 isolation, credential, or resource bound.6566## Where the sandbox leaks6768- **Network access from the runtime.** Egress lets generated code exfiltrate to the outside and reach internal69 services and metadata endpoints.70- **A writable or shared host filesystem.** A host mount, a shared volume, or a writable root lets code read71 secrets and persist beyond the run.72- **Ambient credentials in scope.** An API key, cloud role, or service-account token the runtime can read turns73 execution into credential theft.74- **Thin isolation.** A shared kernel, a dangerous capability or mount, or a bare subprocess is escapable by a75 known primitive, so the guest becomes the host.76- **Missing resource bounds.** No CPU, memory, time, or output limit lets one model-driven run starve or hang77 the host and neighboring sessions.7879## Worked example (a confirm and a kill)8081> **Confirm.** A code-interpreter feature runs model-generated Python in a container that has outbound network82> access and a mounted cloud service-account token. A prompt that steers the model into emitting code which83> reads the token file and posts it to an external endpoint succeeds, exfiltrating a credential that grants cloud84> access. **Confirmed** sandbox credential theft via egress and mounted token, `critical`, remediation = remove85> ambient credentials from the runtime, block network egress by default, and mount no host secret into the86> code-execution sandbox.87>88> **Kill.** The runtime runs generated code with no network egress, an ephemeral filesystem with no host mount89> or shared volume, no credentials or metadata reachable in its environment, hard CPU/memory/time/output limits,90> and isolation that resists a known escape primitive. Probing code cannot reach the network, the host91> filesystem, a credential, or the host. **Killed**, `kill_reason` = "no egress, no host-shared filesystem, no92> ambient credentials, enforced resource bounds, and isolation holds; model-driven code touches nothing outside93> the jail."9495## Rationalizations to reject9697- *"It only runs the user's own code."* → The model's output is shaped by attacker-influenceable input; treat98 everything the runtime executes as hostile and bound it accordingly.99- *"It is in a container."* → A container is not a sandbox by itself; confirm no host mount, no dangerous100 capability, no egress, and no known escape primitive.101- *"There are no secrets in there."* → Enumerate the environment, metadata, and mounted tokens from inside the102 runtime; ambient credentials are the most common one people forget.103- *"We need network for it to be useful."* → Then allowlist specific destinations; open egress lets generated104 code exfiltrate and reach internal services and metadata.105- *"Runs are short."* → Without enforced CPU, memory, time, and output bounds a single run can still starve or106 hang the host; short is not bounded.107108## Executing this in practice109110You need the runtime's network policy, its filesystem view and any host sharing, the credentials reachable from111inside, the isolation mechanism, and the resource limits. Drive the model to emit code that probes each: an112egress beacon, a host-path read and write, a credential enumeration, and a resource-exhaustion loop. Reading the113sandbox configuration shows the intended boundary; code that reaches the network, the host, or a credential114shows whether it holds.115116## Related117118- `auditing-ai-agent-permissions` - the agency and approval layer above the runtime; excessive agency plus a119 weak sandbox is how a tool call becomes host access.120- `auditing-mcp-tool-integrations` - tools an agent calls are the other execution surface; their arguments reach121 the same shells and paths this skill jails.122- `hunting-container-escape-surface` - the container-isolation mechanics a code sandbox depends on; the escape123 primitives are shared.124- `auditing-ml-inference-endpoint-abuse` - the model serving that produces the code; abusing the endpoint and125 escaping the runtime are the two halves of the AI-execution surface.126- [FINDING-SCHEMA.md](../../FINDING-SCHEMA.md) - source = the model-generated code or tool argument, sink = the127 host resource it reaches, evidence = the missing isolation, credential, or resource bound.