Guides

Secrets, egress and blast radius

Guide

How do I restrict which domains an AI agent can reach?

Ask ChatGPT Ask Claude

Start from deny-all and allow only the hosts the agent's work needs. On Sanbox, every template has a network policy: outbound traffic is denied by default, each rule allows one destination on the ports you list, and a blocked request names the host it couldn't reach, so you add hosts on purpose rather than by guesswork. On your own machines the same idea means an egress proxy or firewall with an allowlist. Inbound access is a separate setting and is off by default.

Run this with your agent

Read https://sanbox.cloud/kb/security/restrict-which-domains-an-agent-can-reach.md and follow it to give my agent a template with an egress allowlist.
If the Sanbox CLI is missing, install it with `npm install -g @sanlabs/sanbox-cli@latest`
and sign in with `sanbox login`. Show me each command before you create, stop or delete a Computer.

How does a Sanbox network policy work?

  • Deny by default. A template without a policy reaches nothing except what Sanbox manages for it, such as the model provider configured on the template.
  • One rule per destination. Each rule names a host and a range of ports, with an optional description of up to 120 characters. A template can own at most 16 rules, so list what the work needs, not everything it might.
  • Outbound only. The policy says nothing about who can reach the Computer.
  • Everything inside goes through it. On a Docker Computer, containers and image builds use the same proxy and the same rules.
  • Your own agents need their own hosts. If you install Claude Code or Codex in a Computer, allow its API host yourself.

Steps

1. Write the policy

This example lets a Node and Python coding agent install packages and read from GitHub. Save it as policy.json:

{
  "default_action": "deny",
  "rules": [
    { "destination": "registry.npmjs.org", "ports": [{ "from": 443, "to": 443 }], "description": "npm" },
    { "destination": "pypi.org", "ports": [{ "from": 443, "to": 443 }], "description": "PyPI index" },
    { "destination": "files.pythonhosted.org", "ports": [{ "from": 443, "to": 443 }], "description": "PyPI files" },
    { "destination": "github.com", "ports": [{ "from": 443, "to": 443 }], "description": "git over HTTPS" },
    { "destination": "codeload.github.com", "ports": [{ "from": 443, "to": 443 }], "description": "GitHub archives" }
  ]
}

2. Create the template

Creating templates needs the admin or owner role. The same option works for every Computer type:

sanbox templates create --name "Node and Python agent" --type opencode-computer \
  --model-provider <provider-id> --model <model-id> \
  --network-policy policy.json --json
sanbox templates validate <template-id> --json

runnable: true means the template can start. It doesn't check that the policy allows the sites your task needs.

3. Test from a Computer

Start a Computer, wait until it's running, then try an allowed host and one you left out:

sanbox run --template <template-id> --json
sanbox exec <run-id> -- curl -sS -o /dev/null -w '%{http_code}\n' https://registry.npmjs.org/
sanbox exec <run-id> -- curl -sS https://example.org/

The first prints an HTTP status code. The second fails, because the policy blocks the connection.

4. Add hosts on purpose

When a package install or image pull is blocked, its error names the host it couldn't reach. Decide whether you trust that host, then add it in the template's Network access tab in the console. Test the change on a new Computer. A Secret Proxy grant with --add-network-access also adds an HTTPS rule for the proxy's host.

Which hosts do common tools need?

ToolHostsPort
npmregistry.npmjs.org443
pip and PyPIpypi.org, files.pythonhosted.org443
apt on Debiandeb.debian.org, and security.debian.org if your sources list it80 or 443, as your sources say
Docker Hubregistry-1.docker.io, auth.docker.io, production.cloudfront.docker.com, production.cloudflare.docker.com443
GitHub Container Registryghcr.io, pkg-containers.githubusercontent.com443
GitHubgithub.com, api.github.com, codeload.github.com443
GitHub release downloadsobjects.githubusercontent.com, release-assets.githubusercontent.com443
Raw files on GitHubraw.githubusercontent.com443
Claude APIapi.anthropic.com443
OpenAI APIapi.openai.com443

Two things to watch:

  • Debian sources often use plain HTTP. Look in /etc/apt/sources.list.d/ and allow the port the source URL uses, or switch the sources to https://.
  • Downloads often redirect. A file requested from one host may be served from a separate download or CDN host, and each host in the chain needs a rule. GitHub publishes its current domains in its meta API.

How do I find out what a tool needs?

  • Run it once in a Computer and read the host it couldn't reach from the error.
  • Check the tool's documentation. Claude Code, for example, publishes the domains it needs: api.anthropic.com for the API, plus claude.ai and platform.claude.com for signing in.
  • Prefer specific hosts. Allow api.github.com for an API client rather than every GitHub host.

What about inbound traffic?

Inbound access is off by default and separate from the network policy. To reach a service inside a Computer, an admin adds ports to the template with --inbound-port <port> at creation or sanbox templates inbound set <template-id> --port <port> --json later. Callers then need a short-lived token from sanbox ports connect <run-id> --port <port> --expires 1h --json, or a local forward with sanbox ports forward <run-id> 3000:<port>. Nothing becomes public. HTTP and SSE work; WebSockets and raw TCP don't.

What this doesn't do

  • An allowed host can receive data. If the agent can reach github.com or an API, it can send what it reads there. An allowlist narrows the ways out; it doesn't remove them.
  • Rules work per host and port, not per URL path. To limit what an agent can do with an API credential, use Secret Proxy path and method rules.
  • It doesn't promise a fixed source IP. If a service only accepts known IP addresses, ask support@sanlabs.ai before you plan on it.
  • It isn't a database tunnel. This page covers web traffic. Ask support before you plan on reaching a database over its own protocol.

Sources