Firecracker microVM sandbox · Apache-2.0
Untrusted code runs as root. It still can't reach anything you didn't allow.
isopod boots a real hardware-isolated microVM, runs one command inside it, and destroys it — in about 0.4 seconds. Egress policy lives on the host, outside the sandbox, where nothing in the guest can reach it.
Real rows from a real run. The fourth one never reached the proxy at all — the packet filter dropped it, which is how you can tell the two enforcement layers are independent. Every attempt above is reproducible from the egress ledger.
Two layers, both outside the guest
A run given an allowlist claims a network slot that forwards nothing. Its only reachable peer is a broker on the host. Neither control is reachable from inside the sandbox, and neither needs root at run time.
flowchart TB
G["guest code, running as root on a filtered slot"]
G --> NFT{"nftables, written once as root"}
NFT -->|"port 53, to any destination"| DNS["broker DNS responder"]
NFT -->|"the slot gateway on 1080 or 3128"| PX["broker SOCKS5 and HTTP proxy"]
NFT -->|"everything else"| DROP["dropped at the tap"]
DNS --> POL{"on this run's allowlist?"}
PX --> POL
POL -->|"yes"| OK["resolved and dialled by the broker"]
POL -->|"no"| NO["NXDOMAIN or 403, and recorded"]
| Packet filter | nftables, written once as root A filtered slot drops all forwarding. The only way in is a three-port accept on that slot's own gateway, pinned to the arrival interface and exact destination. |
|---|---|
| Egress broker | SOCKS5 · HTTP · DNS, on the host Resolves and dials on the guest's behalf, only for allowlisted destinations. DNS aimed at any resolver is intercepted, so hardcoded 8.8.8.8 is policy-enforced rather than merely broken. |
| Flight recorder | Every decision, with volume Allowed and denied destinations, bytes moved, and every name resolved — inline in the result and complete on disk as JSON Lines. |
| Isolation | KVM + Firecracker seccomp Not a shared kernel. Firecracker runs unprivileged with all capabilities dropped; an optional rootless jail adds user namespaces and per-VM cgroup caps. |
What holds, and what we don't claim
Both columns are part of the product. A sandbox that only advertises its strengths is asking you to trust it; the limits below are the ones we would want to know.
- A root guest cannot reach a destination that is not on its allowlist, by any protocol.
- A root guest cannot exfiltrate over DNS. Queries to any resolver address are answered by the host.
- A root guest cannot rewrite its own allowlist — the policy is nftables plus a process it cannot address.
- A literal IP is never matched against a name rule, so resolving a name yourself is not a bypass.
- Nothing the guest names reaches your terminal or your model verbatim.
Holds
- This is destination control, not data-loss prevention. Allow
github.comand data can leave togithub.com. - No TLS interception, so a tunnel to a shared CDN address can carry any SNI the guest chooses.
- Without the optional jail, isolation is single-layer: a hypothetical VMM escape lands as your own user.
- The bypass ledger is re-run per release, not on every push — GitHub's runners have no
/dev/kvm.
Not claimed
Try it
One root step to provision host networking. Everything after that is unprivileged.
# One-time, the only step that needs root
sudo isopod setup
# Default-deny egress: only these two hosts are reachable
isopod run --allow-host pypi.org --allow-host '*.pythonhosted.org' \
--stage base --base base-alpine -- pip install requests
# Or: deny everything, and find out what the code reaches for
isopod run --deny-egress --stage base -- node index.js
Driven the same way from Claude Code as an MCP tool —
sandbox_run(cmd=…, allow_hosts=["pypi.org"]) returns the same
verdict record. See MCP usage.
Measured, on a real host
Timings read from isopod's own JSON output, so they are isopod's overhead — not a workload's runtime.
| Warm resume | ~49 ms p50, snapshot restore |
|---|---|
| Cold boot | ~0.44 s p50, boot → exec → destroy |
| Throughput | ~850 VMs/min 6-way concurrency on a 4-vCPU host |
| Filtered egress | no extra boot cost allowlisted runs stay warm-pool eligible |
Full distributions, methodology and caveats in Benchmarks.