Runtime

How to restrict a sandbox to an allow-list of hosts

Create the sandbox with network: { internet: true, allow: ["pypi.org", "*.pythonhosted.org"] }; every other destination is refused.

On Runtime the allow-list is held by a proxy on the host, outside the microVM, so code running as root inside the sandbox cannot widen it. Programs that honour HTTP_PROXY and programs that open raw sockets meet the same rule. A change applies at once, to connections already open too. The narrowed sandbox is still a full Firecracker microVM, from $0.03125 an hour at 2 vCPU and 4 GiB while it waits (pricing).

Allow a list at create

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({  network: { internet: true, allow: ["pypi.org", "*.pythonhosted.org", "github.com"] },});await sbx.exec("pip install requests", { check: true, timeoutMs: 120_000 });const other = await sbx.exec("curl -sS --max-time 5 https://example.com", { timeoutMs: 30_000 });console.log(other.exitCode !== 0); // true: example.com is not on the list
Pythonfrom withruntime import Sandboxwith Sandbox.create(network={"internet": True,                             "allow": ["pypi.org", "*.pythonhosted.org", "github.com"]}) as sbx:    sbx.exec("pip install requests", check=True, timeout_ms=120_000)    other = sbx.exec("curl -sS --max-time 5 https://example.com", timeout_ms=30_000)    print(other.exit_code != 0)  # True: example.com is not on the list
Terminalruntime sandbox create --allow pypi.org --allow '*.pythonhosted.org' --allow github.com

Change the list later

sbx.network.set(...) replaces the rules as a whole, so send the complete list each time:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.network.set({ internet: true, allow: ["registry.npmjs.org"] });await sbx.exec("npm install left-pad", { check: true, timeoutMs: 120_000 });await sbx.network.set({ internet: true, allow: ["api.openai.com"] }); // npm is now refusedconsole.log(await sbx.network.get());
Pythonfrom withruntime import Sandboxwith Sandbox.create() as sbx:    sbx.network.set(internet=True, allow=["registry.npmjs.org"])    sbx.exec("npm install left-pad", check=True, timeout_ms=120_000)    sbx.network.set(internet=True, allow=["api.openai.com"])  # npm is now refused    print(sbx.network.get())
Terminalruntime sandbox network <id> --allow registry.npmjs.orgruntime sandbox network <id>            # show the current rules

MCP agents change rules with runtime_sandbox_network_set.

What an entry can be

Entry Matches
pypi.org That name exactly
*.pythonhosted.org Every name under the domain
203.0.113.7 One address
198.51.100.0/24 A CIDR range
connect: ["db.example.com:5432"] A host:port pair beyond the web ports, on a paid sandbox

An allowed host is reachable on every port the sandbox may use: 80 and 443 on the trial, any port on a paid sandbox once the account has made a purchase. deny entries still win over allow (block a domain).

Allow-lists for common jobs

Job Entries
Python packages pypi.org, *.pythonhosted.org
npm packages registry.npmjs.org
GitHub, clone and raw files github.com, *.githubusercontent.com
One model API That API's host, such as api.openai.com

Mistakes and how Runtime handles them

  • Adding one host with set. A set replaces the rules, so a call that names only the new host drops the old ones. Read the current list with sbx.network.get() and send every entry you still need.
  • Forgetting a CDN. Registries often serve files from a second domain, which is why PyPI needs *.pythonhosted.org as well as pypi.org.
  • Clone over SSH on a narrowed paid sandbox. github.com:22 is not a web port; add it with connect, or clone over HTTPS.
  • Expecting the list to open private addresses. Private and internal addresses are refused whatever the rules say, and mail ports 25, 465 and 587 stay closed unless support enables mail for the account.
  • A key in the sandbox for the one allowed API. Store it as a secret for that host instead, and the sandbox never holds it.

Facts on this page were checked on 25 September 2026.