On Runtime, a deny entry always wins. It wins over any allow entry, and over
root inside the sandbox. The rule lives in a proxy on the host, not in the
guest's firewall. Running sudo iptables in the sandbox does not change what
leaves it. The rule takes effect immediately, including for connections already
open. That makes it a switch you can use while an agent is in the middle of a
task.
Block at create
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ network: { internet: true, deny: ["example.com", "*.example.com"] },});const blocked = await sbx.exec("curl -sS --max-time 5 https://www.example.com", { timeoutMs: 30_000,});console.log(blocked.exitCode !== 0); // true: refused on the hostPythonfrom withruntime import Sandboxwith Sandbox.create(network={"internet": True, "deny": ["example.com", "*.example.com"]}) as sbx: blocked = sbx.exec("curl -sS --max-time 5 https://www.example.com", timeout_ms=30_000) print(blocked.exit_code != 0) # True: refused on the hostTerminalruntime sandboxes create --deny example.com --deny '*.example.com'example.com matches the name itself. *.example.com matches every name under
it. List both to cover a whole site.
Block while it runs
An agent that starts to misbehave can lose a destination without being stopped.
set replaces the rules, so include every rule you still want:
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.spawn("python3 -m http.server 8000");await sbx.network.set({ internet: true, deny: ["pastebin.com"] });console.log(await sbx.network.get()); // the process keeps runningPythonfrom withruntime import Sandboxwith Sandbox.create() as sbx: sbx.spawn("python3 -m http.server 8000") sbx.network.set(internet=True, deny=["pastebin.com"]) print(sbx.network.get()) # the process keeps runningTerminalruntime sandboxes network <id> --deny pastebin.comProcesses, files and memory are not changed. Only the refused connections end.
An agent on MCP does the same with runtime_sandboxes_network, action set.
What a deny entry can name
| Entry | Blocks |
|---|---|
example.com |
That name |
*.example.com |
Every name under it |
203.0.113.7 |
One address |
198.51.100.0/24 |
A CIDR range |
Deny, allow or off?
| You know | Use |
|---|---|
| The few places that are off-limits | deny: everything else stays reachable |
| The few places the code needs | allow: everything else refused |
| The code needs no network at all | internet: false |
A deny list is the lightest rule, and the weakest guard. A site you did not
think of stays open. For code you do not trust, an allow-list is the safer
default. Inside an allow-list, deny carves out exceptions under an allowed
wildcard. One example is a single subdomain of *.githubusercontent.com.
Blocked whatever you set
Some destinations are refused for every sandbox, even without a rule:
- private and internal addresses, so a sandbox never reaches your network;
- mail ports 25, 465 and 587, unless support enables mail for the account;
- telnet, Windows RPC, NetBIOS and SMB, and IRC.
TCP leaves a sandbox. A paid sandbox also sends UDP to any public address and port, under the same rules. A blocked domain is therefore blocked over UDP too (outbound UDP). Names are resolved inside the sandbox.
Mistakes and how Runtime handles them
- Blocking
example.comand expectingwww.example.comto fail. Add the wildcard*.example.comtoo. - Chasing every mirror of a site. A deny list grows without limit when a site has many names. When the list of places the code needs is shorter, switch to an allow-list.
- Losing the old rules. Each
setreplaces the rules. Read them withsbx.network.get()first, and send the full list back. - Trying to block inside the guest. The code you are guarding against can
undo
/etc/hostsoriptableschanges in the sandbox. It cannot undo the host's rule.
Related
- The network in the sandbox environment guide.
- Network access.
- Egress control.
- Run untrusted LLM code.
Facts on this page were checked on 26 October 2026.