# How to turn off internet access in a sandbox Create the sandbox with `network: { internet: false }`, or call `sbx.network.off()` at any time; every outbound connection is refused. **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, which applies the rule at once, to connections already open too. The same call narrows access to a list of hosts instead. A new sandbox ran its first Python command 351 ms after the request at the median on 24 September 2026 ([speed](/docs/speed)), so a fresh offline machine per task is practical. ## Offline from the start ```ts import { 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 refused ``` ```python from withruntime import Sandbox with 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 refused ``` ```bash no-run runtime sandbox create --no-internet ``` ## Install first, then cut it off Most jobs need a package before they run untrusted code. Let the sandbox reach only the registry, install, and turn the internet off: ```ts check import { 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()); ``` ```python check from withruntime import Sandbox with 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()` gives back the account's normal access, and `runtime sandbox network --no-internet` does the same from the CLI. An agent connected through MCP uses `runtime_sandbox_network_set`. ## The rules | Rule | What it does | | ------------------------------------ | ------------------------------------------------------------------------------------------------- | | `internet: false` | Refuses every outbound connection | | `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 them at create with `network`, or at any time with `sbx.network.set(...)`, which replaces the rules. They apply at once, to open connections too, and they bind root inside the sandbox ([the network](/docs/sandbox-environment#the-network)). Some things 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. TCP leaves a sandbox, and a paid one also sends QUIC and NTP over UDP ([outbound UDP](/docs/networking#outbound-udp)); DNS is answered inside it. ## What still works offline - **Everything inside the sandbox:** commands, files, background processes and the code interpreter. - **Your control of it:** `exec` and 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 sandbox ssh` and `runtime sandbox port-forward` are the ways in, and each is yours to open ([network access](/docs/security#network-access)). ## When the code needs one API Turning the internet off is the strongest setting. When code must call one service, allow only that host and store its key as a [secret the sandbox never sees](/docs/security#secrets-sandboxes-never-see): the sandbox holds a placeholder, and the host's proxy adds the real key only on HTTPS requests to the hosts you named. ```ts check import { 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"] }, }); ``` ```python check import os from withruntime import Runtime runtime = 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 a worthless placeholder, and code that tries to send your data anywhere else is refused. ## Where this matters - [Running untrusted LLM code](/use-cases/run-untrusted-llm-code): model output runs with no route out. - [Grading student code](/use-cases/grade-student-code): submissions cannot fetch answers or phone home. - [Egress control](/glossary/egress-control) explains allow and deny lists in general. Each sandbox also has limits on concurrent connections, bandwidth and bytes a day, so one sandbox cannot crowd out others. ## Start ```bash no-run npx withruntime sandbox run --trial --no-internet -- python3 -c 'print(6 * 7)' ``` New accounts get 50 free sandbox hours, no card. The first run prints a link to approve in your browser. Facts on this page were checked on 25 September 2026.