On Runtime, the rule is enforced on the host, so root inside the sandbox cannot undo it. A sandbox has no network card. Everything it sends goes through a proxy outside the microVM. The proxy applies the rule immediately, including to connections that are already open. The same call can narrow access to a list of hosts instead. A fresh offline machine per task costs only the time it runs.
Offline from the start
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ network: { internet: false } });const run = await sbx.exec("curl -sS --max-time 5 https://example.com", { timeoutMs: 30_000 });console.log(run.exitCode !== 0); // true: the connection is refusedPythonfrom withruntime import Sandboxwith Sandbox.create(network={"internet": False}) as sbx: run = sbx.exec("curl -sS --max-time 5 https://example.com", timeout_ms=30_000) print(run.exit_code != 0) # True: the connection is refusedTerminalruntime sandboxes create --no-internetInstall first, then cut it off
Most jobs need a package before they run untrusted code. Let the sandbox reach only the registry, install the package, and then turn the internet off:
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ network: { internet: true, allow: ["pypi.org", "*.pythonhosted.org"] },});await sbx.exec("pip install requests", { check: true, timeoutMs: 120_000 });await sbx.network.off(); // same as network.set({ internet: false })console.log(await sbx.network.get());Pythonfrom withruntime import Sandboxwith Sandbox.create(network={"internet": True, "allow": ["pypi.org", "*.pythonhosted.org"]}) as sbx: sbx.exec("pip install requests", check=True, timeout_ms=120_000) sbx.network.set(internet=False) print(sbx.network.get())sbx.network.on() restores the account's normal access. The command
runtime sandboxes network <id> --no-internet does the same from the CLI. An
agent connected through MCP uses runtime_sandboxes_network, action set.
The rules
| Rule | What it does |
|---|---|
internet: false |
Refuses every outbound connection. With an allow list, it refuses everything except the list |
allow: ["pypi.org", "*.npmjs.org"] |
Only these domains, *.domain names, addresses or CIDR ranges, on every port the sandbox may use |
deny: ["example.com"] |
Always refused; deny wins over allow |
connect: ["db.example.com:5432"] |
A host:port beyond the web ports when allow narrows a paid sandbox |
sbx.network.get() |
The current rules; openPorts: true when every port is reachable |
Set the rules when you create the sandbox with network, or at any time with
sbx.network.set(...). The call replaces the rules. They apply immediately,
including to open connections, and they bind root inside the sandbox
(the network).
The following are refused whatever the rules say:
- private and internal addresses, so a sandbox never reaches your network;
- mail ports 25, 465 and 587, unless support enables mail for your account;
- telnet, Windows RPC, NetBIOS and SMB, and IRC.
A sandbox sends TCP out. A paid sandbox also sends UDP to any public address
and port. The same rules cover UDP, so internet: false stops UDP as well
(outbound UDP). DNS queries are answered inside
the sandbox.
What still works offline
- Everything inside the sandbox: commands, files, background processes and the code interpreter.
- Your control of it:
execand file calls come in through Runtime's API, so a sandbox with the internet off still runs your commands and returns their output. - Ways in that you open: nothing on the internet can connect to a sandbox.
A private preview,
runtime sandboxes sshandruntime sandboxes port-forwardare the ways in. You open each one yourself (network access).
When the code needs one API
Turning the internet off gives the strictest protection. When code must call one service, allow only that host. Store its key as a secret the sandbox never sees. The sandbox holds a placeholder. The host's proxy adds the real key only to HTTPS requests to the hosts you named.
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.secrets.set("OPENAI_API_KEY", { value: process.env.OPENAI_API_KEY ?? "", hosts: ["api.openai.com"],});await using sbx = await runtime.sandboxes.create({ network: { internet: true, allow: ["api.openai.com"] },});Pythonimport osfrom withruntime import Runtimeruntime = Runtime()runtime.secrets.set("OPENAI_API_KEY", value=os.environ.get("OPENAI_API_KEY", ""), hosts=["api.openai.com"])with runtime.sandboxes.create(network={"internet": True, "allow": ["api.openai.com"]}) as sbx: print(sbx.network.get())Code that leaks the key sends only a placeholder that has no value. Code that tries to send your data anywhere else is refused.
Where this matters
- Running untrusted LLM code: model output runs with no route out.
- Grading student code: submissions cannot fetch answers or phone home.
- Egress control explains allow and deny lists in general.
Each sandbox also has limits on concurrent connections, bandwidth and bytes per day. These keep one sandbox from crowding out others.
Start
Terminalprintf '%s\n' 'print(sum([125, 250, 375]))' > invoice.pynpx withruntime sandboxes run --no-internet -- python3 - < invoice.pyA new account gets 100 free hours of a 1 GB machine in its first 30 days, with no card required. The first run prints a link to approve in your browser.
Facts on this page were checked on 26 October 2026.