# 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, a proxy on the host holds the allow-list. The proxy runs outside the microVM, so code running as root inside the sandbox cannot widen the list.** Programs that honor `HTTP_PROXY` and programs that open raw sockets meet the same rule. A change takes effect immediately, including for connections that are already open. The narrowed sandbox is still a full Firecracker microVM. It costs $0.03125 an hour at 2 vCPU and 4 GiB while it waits ([pricing](/docs/pricing)). ## Allow a list at create ```ts check import { 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 ``` ```python check from withruntime import Sandbox with 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 ``` ```bash no-run runtime sandboxes create --allow pypi.org --allow '*.pythonhosted.org' --allow github.com ``` ## Change the list later `sbx.network.set(...)` replaces the rules as a whole. Send the complete list each time: ```ts check import { 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 refused console.log(await sbx.network.get()); ``` ```python check from withruntime import Sandbox with 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()) ``` ```bash no-run runtime sandboxes network --allow registry.npmjs.org runtime sandboxes network # show the current rules ``` MCP agents change rules with `runtime_sandboxes_network`, action `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. On the trial, that is ports 80 and 443. On a paid sandbox, it is any port once the account has made a purchase. `deny` entries still win over `allow` ([block a domain](/how-to/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. 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. That is why PyPI needs `*.pythonhosted.org` as well as `pypi.org`. - **Cloning 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. 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 the key as a [secret](/how-to/use-secrets-in-a-sandbox) for that host instead. The sandbox then never holds it. ## Related - [The network](/docs/sandbox-environment#the-network): every rule. - [Egress control](/glossary/egress-control), the general idea. - [Turn off sandbox internet](/how-to/turn-off-sandbox-internet) for no destinations at all. - [Coding agent sandbox](/use-cases/coding-agent-sandbox). Facts on this page were checked on 26 October 2026.