Skip to main content

Security and limits

This page states, plainly, what protects your platform when untrusted code runs in the sandbox — and what does not. The big clouds tend to bury this; we put it on one page, including the parts that are not flattering.

The security model in one paragraph

Model-generated code runs in a pod that is created before it is needed, used exactly once, and destroyed. The pod runs as a non-root user, holds no cluster credentials, and its network is cut off except for DNS. If the code loops forever, a hard timeout kills the whole process group. If it floods output, the pod's memory limit kills the pod — not the node. Nothing the code does in one run can affect the next run, because there is no next run in that pod.

One pod, one run

A sandbox pod is never used twice. Two consecutive executions always report different sandbox_id values. This is the property that AWS and Azure session-based sandboxes make optional (sessions persist and are reused); here it is the only mode. There is no state to scrub between calls because the entire environment is thrown away.

Files written during a run are destroyed with the pod. If your workflow needs state across runs, keep it in your agent's session, not in the sandbox.

No network egress (for code snippets)

Snippet pods (the ones behind run_python and /v1/execute) can make DNS lookups (port 53, UDP and TCP) and nothing else. An HTTP fetch from model-generated code fails:

curl -s -X POST "$SANDBOX/v1/execute" \
-H "Content-Type: application/json" \
-d '{"code":"import urllib.request\nurllib.request.urlopen(\"https://example.com\", timeout=5)","timeout_s":15}'

You should see (traceback trimmed):

{"sandbox_id":"sandbox-2m8rt","stdout":"","stderr":"Traceback (most recent call last):\n ...\nurllib.error.URLError: <urlopen error ...>","exit_code":1,"duration_ms":5041}

The name resolves; the connection never opens. Malicious code cannot call home, download payloads, or reach internal services.

DNS stays open — and that is a known channel

DNS is allowed so name resolution failures don't masquerade as timeouts. Honest caveat: an open DNS channel can, in principle, be used to tunnel small amounts of data out via crafted lookups. AWS's equivalent product shipped with the same gap and had it publicly disclosed by researchers before it was patched. We are telling you up front instead.

Tool-call pods are different — on purpose

Sandboxed tool calls (/v1/call) run your own code from the agent's own image, so by default they can reach the public internet — a weather tool that cannot fetch weather is useless. What they can never reach:

  • 169.254.0.0/16 — cloud metadata endpoints (where instance credentials live),
  • 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 — private and cluster-internal networks.

And the pod starts with an empty platform environment: no model API key, no store token, no messaging credential. The missing credentials are the security boundary — a prompt-injected tool call has nothing to steal. Internet egress for tool pods is a platform setting (toolCalls.allowInternetEgress, on by default).

Non-root, no capabilities

Sandbox pods run under Kubernetes' restricted security profile: a non-root user, no privilege escalation, all Linux capabilities dropped, and the default seccomp filter (a kernel-level syscall allowlist). The pod also has no ServiceAccount credentials, so code inside it cannot talk to the Kubernetes API at all.

Honest caveat: the default runtime is plain runc — standard container isolation, enforced by the shared Linux kernel. AWS uses micro-VMs and Azure uses Hyper-V isolation, which are stronger against kernel exploits. Clusters that have gVisor installed can enable it for sandbox pods via the runtimeClassName setting; it is empty by default.

Timeouts kill, memory limits contain

  • Every run has a hard wall-clock limit (default 20 s, max 60 s for snippets). At the deadline the entire process group is killed; you get exit_code: -1 and stderr: "timed out after <N>s". A while True: pass cannot hold a pod.
  • Output (stdout and stderr) is buffered in the pod's memory. A print flood hits the pod's 512 MiB memory limit and the pod is killed — the node, and everyone else's workloads, are unaffected.

All limits in one table

LimitValue
LanguagePython only
Snippet timeout (/v1/execute)default 20 s, max 60 s
Tool-call timeout (/v1/call)default 30 s, max 120 s
Warm pool size3 pods (platform-managed)
Wait when the pool is empty30 s, then 503 no warm sandbox pod available, try again shortly
Snippet pod resources1 CPU, 512 MiB memory (hard limits)
Tool-call pod resources2 CPU, 1 GiB memory (hard limits)
Tool-call request body1 MiB
Tool-call response8 MiB
Tool pod readiness deadline110 s (scheduling + image pull; there is no warm pool for tool calls)
Input file pathsmust stay inside the working directory
Pod reusenever
Files after a rundestroyed with the pod

What this model does not do — the honest list

  • The sandbox service itself has no authentication. sandboxd is protected purely by network position: it is reachable only inside the cluster, and agents receive its address through the reserved SANDBOX_URL environment variable, which cannot be overridden — so an agent cannot be repointed at a fake sandbox. It must never be exposed outside the cluster.
  • Tool sandboxing can be switched off. Setting TOOL_SANDBOX=false on an agent runs tool code inside the agent's own pod, next to its credentials. Only do this if you fully trust every tool. The reverse failure is safe: if the sandbox is unreachable, the agent fails closed — it errors rather than silently running the code beside its credentials.
  • Kernel isolation, not hardware isolation, by default. See the runc note above.
  • DNS egress is open in snippet pods. See the warning above.

Summary checklist

PropertySnippet pods (run_python)Tool-call pods
Used more than onceNeverNever
Internet accessNo (DNS only)Yes by default; metadata + private ranges always blocked
Platform credentials insideNoneNone
Runs as rootNoNo
Hard timeout20 s default, 60 s max30 s default, 120 s max
Warm pool (fast start)Yes (~1 s)No (pays pod start + image pull)

Next: Run code in the sandbox · Code Sandbox overview