Skip to content

Deny by default

sandboxio.create() with no arguments gives a sandbox that cannot open a single outbound connection. Not "a sandbox with a firewall you can configure" — one that starts closed, and opens only where you say so.

examples/04_egress_denied.py proves this on a real sandbox in about twenty lines, then shows the explicit opt-out.

The threat this answers

An agent's code is at best buggy and at worst attacker-chosen through prompt injection. sandboxio cannot prevent the injection. It bounds the blast radius: whatever runs in the sandbox cannot exfiltrate the data it was given, cannot fetch a second stage, and cannot call an API with credentials it found lying around. Egress is the channel for all three, so egress is off (spec/05).

Mandatory timeouts and resource caps sit beside it for the same reason: an unbounded execution is a cost and a denial-of-service waiting to happen, so timeout=None is refused rather than interpreted as "forever".

What the default costs, honestly

Dependencies. pip install from inside the sandbox does not work, and this project's own first draft carried a streaming example that did exactly that. The answer is not a setup window with the network open — a policy that varies over a sandbox's life makes "the policy in effect" a time-varying fact the audit record cannot state. The answers are images with dependencies baked in and offline wheelhouses uploaded through files (Docker how-to), or an allowlist on a backend that can enforce one (E2B how-to).

Image pulls are unaffected: docker pull runs on the host daemon, outside the container's network namespace. That confusion generated an open question in this project's history, and is worth stating plainly.

The rule that makes it trustworthy

A backend that cannot enforce a requested policy raises CapabilityNotSupported. It does not approximate, it does not warn and continue. Docker has no per-host egress filtering, so a NetworkPolicy(allow=...) against Docker raises instead of quietly granting full bridge access (ADR-0023). Accepting and ignoring a network policy is the single most dangerous bug this library could have (hazard H1), and the contract suite proves deny against a canary host on every real backend.

The same rule covers every typed argument: Resources(disk_mb=...) on Docker and Resources(cpu=...) on E2B are refused, not ignored. Never silently no-op.

Seeing it

uvx sandboxio demo runs an outbound request from inside a fresh sandbox and reports that it was denied — and would fail the demo if it were not. Where a backend reports blocked attempts, the count is in every audit event as network_denials.