When to use this
Two things you did not write meet in one place: an untrusted tool and an untrusted input. Malware analysis, a file-format parser fed a hostile sample, an unaudited third-party scanner, a linter someone attached to a support ticket. The VM boundary already means a crash or arm -rf cannot reach the host. What it does not decide on its own is whether that tool can phone home. A parser that reads your sample and posts it somewhere has not escaped anything — it simply used the network it was given.
This guide stacks the three controls that close that gap:
Architecture
The sample goes in explicitly, the verdict comes out explicitly, and there is no third path — no network, no host filesystem, no shared kernel.Prerequisites
- BoxLite installed and a working virtualization host — see Installation.
- An image containing whatever tool you intend to run. This guide uses
alpine:latestwithfile.
Build it
0.0.0.0: the lookup succeeds and leads nowhere. Parameter tables are on Network access and Secrets and hardening.
Run it
curl line inside the sample is inert — with mode="disabled" there is no interface to use.
Trust and limits
- What the boundary covers. The tool runs on its own kernel and filesystem with its own resource budget, as a non-root user, with no network. Its only outputs are the exit code and the streams you read.
- Isolation and containment are different properties. The microVM stops damage; the network policy stops exfiltration. A default box has full outbound access — that is convenient for most use cases here and wrong for this one. Set the network explicitly here.
user=labels the process, it is not a full identity boundary. It stops casual writes outside the work area. It is one layer among three, not a substitute for the network policy or the VM.security=is not a top-level keyword. It must be wrapped:advanced=AdvancedBoxOptions(security=...). Passing it directly raisesTypeError. The presets aredevelopment(),standard(), andmaximum(); there is nominimum().- Blocked is not the same as failed. With egress narrowed, a request to a blocked host resolves to
0.0.0.0and then fails to connect — you will see a connection error, not a DNS error. Do not read that as “the tool is broken”. execreturns failure as data. A scanner exiting non-zero is a normal result here. Readexit_code; nothing is raised.
Troubleshooting
Next steps
- Apply the same three controls elsewhere. Any use case here that runs model-generated code can adopt them — start with Build a code interpreter.
- Harden a CI pipeline. Review untrusted pull requests needs
github.comand a package mirror allowed, and nothing else. - Keep credentials out of the box. When a tool must authenticate, inject the value at the proxy instead of inside the sandbox — Secrets and hardening.

