Skip to content

Network Isolation

By default, sandboxes have full access to the internet. If you need to run untrusted user code or LLM agents that should not exfiltrate data, you can opt the sandbox into Network Isolation to completely block all outbound network traffic (egress).

When network isolation is enabled:

  • Outbound network calls (e.g., HTTP requests, database connections, DNS lookups) are blocked immediately by the host firewall.
  • Ingress requests on exposed ports (like public URLs or TCP exposures) are still permitted.

To isolate a sandbox, set networkBlockAll (or network_block_all) to true when creating the sandbox.

const sandbox = await client.create({
image: 'ubuntu:22.04',
networkBlockAll: true,
})

Once isolated, executing a command inside the sandbox that requires outbound network access (like curl or package installers) will fail.

const result = await sandbox.exec({
command: 'curl -I https://google.com',
})
console.log(`Exit code: ${result.exitCode}`) // Non-zero exit code due to blocked egress

Network isolation only blocks outbound requests. It does not affect ingress traffic to ports exposed via the SDK's port exposure APIs:

// Expose port 80 to the public internet
const exposure = await sandbox.exposePort(80)
console.log(`Access the isolated sandbox at: ${exposure.url}`)

Services running inside the sandbox remain reachable via their exposed public URLs, even though the sandbox itself cannot initiate connection requests to the internet.


A blanket block is often too strict — an agent may need to reach one specific API while everything else stays blocked. Use networkAllowOut or networkDenyOut to define a per-CIDR egress policy, enforced by the same host firewall:

  • networkAllowOut — the sandbox may reach only these CIDRs; all other outbound traffic is dropped.
  • networkDenyOut — the sandbox may reach anything except these CIDRs.

The two are mutually exclusive. A full block is still expressed with networkBlockAll rather than a 0.0.0.0/0 deny.

// Allow only 1.1.1.0/24 and 8.8.8.8; block everything else.
const sandbox = await client.create({
image: 'ubuntu:22.04',
networkAllowOut: ['1.1.1.0/24', '8.8.8.8/32'],
})

To invert the policy — block a few destinations and allow the rest — pass the same shape to networkDenyOut instead:

const sandbox = await client.create({
image: 'ubuntu:22.04',
networkDenyOut: ['10.0.0.0/8'], // block the internal range, allow the rest
})

The policy is persisted with the sandbox and reapplied automatically across stop/start cycles and host restarts, just like networkBlockAll.


The options above control outbound traffic. Inbound public reachability is a separate decision — and the default is private: a sandbox created without allowPublicTraffic boots with no <sandbox-id>.<domain> ingress route and an empty public_url. The platform's own access paths (the toolbox exec/file proxy and the SSH gateway) always work, since they do not route through the public ingress.

There are two ways to opt in to public exposure:

  1. Call exposePort. Asking for a public port is the consent: the first exposePort on a private sandbox flips it to public — the flag is persisted, the <sandbox-id>.<domain> route is installed, public_url becomes live — and then the port route goes in. No extra step needed.
  2. Set allowPublicTraffic: true at create time if you want the sandbox URL live from boot, before any port is exposed:
const sandbox = await client.create({
image: 'ubuntu:22.04',
allowPublicTraffic: true,
})
// sandbox.publicUrl is live from boot, before any exposePort call.

The opt-in is one-way and sandbox-wide: once a port has been exposed, the sandbox is public (flag, root route, and public_url) and stays public even if every port is later unexposed. Custom domains alone do not flip a private sandbox — attaching a domain to a sandbox you kept private returns an error, so a domain can never silently publish it; expose a port (or create with the flag) first. Private creates also skip the ingress proxy entirely on the boot path, which shaves the route-install round trips off create latency.

The Daytona compatibility facade maps its public field onto this flag (omitted means true, matching Daytona's platform default), and the E2B facade opts in by default for the same reason — E2B sandboxes are publicly addressable by contract.


When you expose a port, traffic reaches your app through the per-sandbox public hostname (e.g. 3000-<sandbox-id>.<your-domain>), and that value arrives as the HTTP Host header. Many dev servers and frameworks reject requests whose Host they don't recognize:

  • Vite (server.allowedHosts) — "Blocked request. This host is not allowed."
  • webpack-dev-server (allowedHosts)
  • Django (ALLOWED_HOSTS), Rails host authorization

Set maskRequestHost to rewrite the upstream Host header to a value your app accepts — typically localhost. The public URL is unchanged; only the header your service sees changes. Leave it unset to pass the host through untouched.

const sandbox = await client.create({
image: 'node:22',
maskRequestHost: 'localhost',
})

The rewrite applies to HTTP port exposures only and is enforced consistently whether the sandbox serves traffic directly or wakes from a paused state. Raw TCP and TLS-passthrough exposures carry no Host header, so the value is ignored for them.


If you do not want to block all network traffic permanently, you can use the SDK's Network Usage & Quotas features to set limits on total bytes sent or received.

Using the limits API, you can:

  • Define maximum ingress/egress bytes at create time.
  • Retrieve live byte counters via getNetworkUsage().
  • Dynamically update limits at runtime using setNetworkLimits().

For details on setting up quotas, see the Network Usage & Quotas guide.


  • IPv4 Only: Network isolation and byte limits are applied to IPv4 routes. If the sandbox has IPv6 routing enabled, those connections are not blocked.
  • CIDR-based, not domain-based: Selective egress (networkAllowOut / networkDenyOut) matches on IP CIDRs, not hostnames. There is no domain allowlist or DNS-only mode — allow the CIDRs your destination resolves to.