Guide · Network allow-list
How do I restrict an AI agent's network access to an allow-list?
Updated
Deny all outbound traffic by default, list only the hosts the agent needs, and enforce that list outside the machine the agent controls, at the packet level, with DNS answered by the enforcer. A DNS filter or an HTTP proxy on its own leaks, because programs can connect to raw IP addresses, ignore proxy settings, or flush a firewall they are root over. In kosa8, kosa8 sandbox create NAME --egress-allow HOST does this, and the list is enforced on your computer, where nothing inside the sandbox can reach it.
01Steps
Install kosa8 on an Apple silicon Mac or x86-64 Linux.
curl -fsSL https://kosa8.com/install.sh | shCreate a sandbox with an allow-list. Repeat
--egress-allowfor each entry. A list implies deny for everything else. An entry can be an exact name, a*.example.comwildcard, an IPv4 address, or a CIDR range.kosa8 sandbox create dev --egress-allow registry.npmjs.org sandbox dev ready in 737ms (32 GB disk)
Use
--egress denyfor no network at all, DNS included. The policy is fixed when the sandbox is created; to change it, create another sandbox.Check what is in force.
kosa8 sandbox egressshows the policy and the counts of passed and denied traffic since boot.kosa8 sandbox egress dev policy: allow:registry.npmjs.org (enforced on the host) frames: 3 passed, 0 denied, 1 dropped as link noise dns: 2 answered, 0 refused
Read the refusals. Each refused attempt is written to the audit log with the action
sandbox.egress.deny.kosa8 audit ls --json -n 0 | jq -r '.[] | select(.target == "dev" and .action == "sandbox.egress.deny") | .detail'For a coding agent, use a kit. The built-in
claude,codex,geminiandopencodekits run with the network closed except through the egress broker, and print the allowed hosts before anything runs.--no-networkdenies everything.kosa8 agent run claude kosa8: network closed except through the egress broker: registry.npmjs.org, statsig.anthropic.com
Set a default for the organisation. Put
"default_egress": "deny"(or"allow:a.com,b.com") in the organisation policy, then sign, pin and install it. It applies to any sandbox created without a rule of its own.kosa8 policy keygen -o org.key kosa8 policy init > profile.json kosa8 policy sign org.key profile.json > signed.json kosa8 policy trust $(cat org.key.pub) kosa8 policy install signed.json
Tool servers get the same flags: kosa8 mcp add accepts --egress and --egress-allow. An AI agent that creates its own sandbox through the MCP sandbox_create tool gets no network unless it asks for one in the call's egress_allow argument.
02What does default-deny egress mean for an AI agent?
Default-deny egress means every outbound connection, datagram and DNS lookup is refused unless its destination is on a list you wrote. The agent can still reach its model provider and package registry, but a prompt injection cannot send your code or keys to a host you did not list.
In kosa8, a refused connection fails at once: a TCP connection gets a reset, a UDP datagram gets an ICMP "administratively prohibited" reply, and a DNS question gets REFUSED. The program sees an error instead of waiting for a timeout.
03Why do DNS-only or proxy-only allow-lists leak?
A DNS filter only controls name lookups, and an HTTP proxy only sees programs that choose to use it. A program that connects straight to an IP address, uses its own resolver, or ignores HTTPS_PROXY goes around both unless a default-deny packet filter sits underneath.
- Raw addresses. Code can dial
1.1.1.1directly. A DNS filter never sees that connection. - Its own resolver. If the sandbox may pick its DNS server, it can get any answer it likes for an allowed name. kosa8 intercepts every DNS query, never forwards it, resolves listed names on your computer, and admits only the addresses your computer looked up.
- Proxy settings are optional.
HTTPS_PROXYis a convention. kosa8's broker runs beside an address policy of deny, so a program that ignores the proxy reaches nothing. - A firewall inside the agent's machine. Root inside a VM or container can flush its own iptables rules. kosa8 keeps an inner firewall for convenience, but the boundary is a network guard in the kosa8d service on your computer that reads every frame the VM sends.
- DNS rebinding. An allowed name can be pointed at
127.0.0.1or169.254.169.254. kosa8 withholds private, loopback and link-local answers for allowed names unless you list that address yourself.
04What does a hostname allow-list still not stop?
An allow-list limits where traffic goes, not what it carries. An allowed host that accepts uploads is still a way out, so allow few hosts.
- Shared addresses. Under address rules, an allowed name admits the addresses it resolves to on every port. If those belong to a content delivery network, other sites on them are reachable too.
- Wildcards and DNS. With
*.example.comallowed, the sandbox can look up any name under it, and whoever runs that domain's name servers can read data encoded in the names. Only allow a wildcard over a domain you trust. - Encrypted tunnels. The broker checks the name and port of an HTTPS
CONNECT, then carries TLS it does not open. - IPv4 only. A kosa8 sandbox has no IPv6 route; IPv6 entries in a list are refused.
To see exactly what a sandbox sent, kosa8 sandbox pcap dev ./dev.pcapng writes every frame to a file Wireshark can open.
05Other options
- Claude Code's built-in
/sandbox. Routes network access through a proxy outside the sandbox with a list of allowed domains. A good fit for Claude Code on its own, with no VM. - Docker.
--network noneor an--internalnetwork removes outside access; pair it with an egress proxy container for an allow-list. - gVisor, Firecracker or Kata Containers. Strong isolation for workloads you run yourself; you build the egress filtering on the host, for example with nftables.
- A full VM in UTM or Lima. Combine with a host firewall or a filtering proxy.
- E2B, Daytona or Modal. Hosted sandboxes with their own network controls; check each provider's docs for whether they filter by hostname or by IP range.