kosa8 / Guides

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

  1. Install kosa8 on an Apple silicon Mac or x86-64 Linux.

    terminal
    curl -fsSL https://kosa8.com/install.sh | sh
  2. Create a sandbox with an allow-list. Repeat --egress-allow for each entry. A list implies deny for everything else. An entry can be an exact name, a *.example.com wildcard, an IPv4 address, or a CIDR range.

    terminal
    kosa8 sandbox create dev --egress-allow registry.npmjs.org
    sandbox dev ready in 737ms (32 GB disk)

    Use --egress deny for no network at all, DNS included. The policy is fixed when the sandbox is created; to change it, create another sandbox.

  3. Check what is in force. kosa8 sandbox egress shows the policy and the counts of passed and denied traffic since boot.

    terminal
    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
  4. Read the refusals. Each refused attempt is written to the audit log with the action sandbox.egress.deny.

    terminal
    kosa8 audit ls --json -n 0 | jq -r '.[] | select(.target == "dev" and .action == "sandbox.egress.deny") | .detail'
  5. For a coding agent, use a kit. The built-in claude, codex, gemini and opencode kits run with the network closed except through the egress broker, and print the allowed hosts before anything runs. --no-network denies everything.

    terminal
    kosa8 agent run claude
    kosa8: network closed except through the egress broker: registry.npmjs.org, statsig.anthropic.com
  6. 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.

    terminal
    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.1 directly. 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_PROXY is 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.1 or 169.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.com allowed, 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 none or an --internal network 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.

06Sources