Sandboxes
Tested with: zb CLI 0.1 · MCP (zb-mcp) · REST API v1
A sandbox is a short-lived, isolated runtime for code you do not trust: code written by an AI agent, user-submitted scripts, or a one-off build. Create one, run commands with streamed output, copy files in and out, snapshot its workspace, and kill it. Templates come with Python 3, Node.js and Git.
Quickstart
Section titled “Quickstart”id=$(zb sandbox create --template python --timeout 600)zb sandbox cp ./analysis.py "$id:analysis.py"zb sandbox exec "$id" -- python3 analysis.py # streams output, exits with the command's codezb sandbox cp "$id:out/report.csv" .zb sandbox kill "$id"Point your agent at the Databasezy MCP server (see MCP), then ask it to use sandbox_create,
sandbox_files_write, sandbox_exec, sandbox_files_read and sandbox_kill. The tools return output, never
credentials.
# 1. Create (returns the sandbox and a short-lived data-plane token).curl -s -X POST "$ZB_API/v1/orgs/$ORG/projects/$PROJECT/sandboxes" -H "Authorization: Bearer $ZB_API_KEY" \ -H "Content-Type: application/json" -d '{"template":"python","timeout_secs":600}'# 2. Run a command on the project endpoint with the token from `access` (or a new session).curl -s -X POST "$EXEC_URL?stream=false" -H "Authorization: Bearer $SANDBOX_TOKEN" \ -H "Content-Type: application/json" -d '{"cmd":["python3","-c","print(6*7)"]}'A session (POST .../sandboxes/{id}/sessions) mints a token for one scope (exec, files:read, files:write),
at most one hour, optionally bound to one file path for a signed download link.
How it works
Section titled “How it works”- Isolation: each sandbox is its own gVisor container, non-root, on nodes separate from databases, with no
Kubernetes credentials and a read-only system:
/workspaceand/tmpare writable. - Lifetime: a sandbox stops after its timeout (default 5 minutes) or when it has been idle (no command) for its idle timeout, whichever comes first. Warm spares make creation fast.
- Commands run without a shell unless you ask for one (
-- sh -c '...'); arguments are never re-parsed. - Snapshots save
/workspace(zb sandbox snapshot) and restore it into a new sandbox (zb sandbox create --from-snapshot snap_...). They expire after their retention. - Billing is per second at the size’s hourly price while the sandbox runs.
Network access
Section titled “Network access”By default a sandbox has no network at all (no DNS either). Choose per sandbox:
--egress | What the sandbox can reach |
|---|---|
none (default) | Nothing. |
internet | The public internet (never private, link-local or cloud metadata addresses; SMTP port 25 is closed). |
allowlist | Only the hosts and public CIDRs you list with --allow (pypi.org:443, *.pythonhosted.org, 45.60.12.0/24:5432). |
Allow-listed hosts go through the region’s egress proxy, which re-checks every address it connects to, so a name that resolves to an internal address is refused.
Cloaked secrets
Section titled “Cloaked secrets”Give a sandbox an API key without giving it the key:
zb secrets set OPENAI_KEY=sk-... # a project secretInside the sandbox OPENAI_API_KEY holds a placeholder (zbcloak_...). When the code sends that placeholder in a
header or query parameter to api.openai.com, the egress proxy swaps in the real value. Sent anywhere else, the
request is refused and the attempt is recorded as a security event, so a malicious dependency cannot exfiltrate the
key. Request bodies are not rewritten.
| Size | vCPU | Memory | $ / hour |
|---|---|---|---|
x1 | 1 | 1 GiB | $0.05 |
x2 | 2 | 2 GiB | $0.1 |
x4 | 4 | 4 GiB | $0.2 |
Pricing and limits
Section titled “Pricing and limits”| Meter | Price | Free | Solo | Team | Enterprise |
|---|---|---|---|---|---|
| Sandbox compute Coming soon | By size, per running second | Not available | Pay as you go | Pay as you go | Pay as you go |
| Limit | Free | Solo | Team | Enterprise |
|---|---|---|---|---|
| Concurrent sandboxes Coming soon | None | 5 | 50 | Unlimited |