Blog / 31 October 2026

Deep dive · 31 October 2026 · 7 min read

Are domain allow-lists enough? How AI agent egress control really works

A domain allow-list is necessary but not enough: it decides where an AI agent can connect, not what it sends there. How much it actually blocks depends on where it is enforced, whether DNS is closed too, and which hosts you allow, because any allowed host that accepts data is still a way out.

ai agent egress controldns exfiltrationproxy vs dns filteringallowed-domain exfiltrationdeny by default egress

01What does egress control mean for an AI agent?

Egress is traffic leaving the agent's environment. Egress control is a rule about that traffic, and for agents the sensible default is deny: nothing leaves unless it is going to a destination you named. That rule can be enforced at three different layers, and they see very different things.

Most real setups combine two or three of these. The rest of this post is about what each layer can and cannot see, because the gaps between them are where data leaves.

  • Address rules: a firewall that allows a list of IP addresses, usually filled in by resolving the allowed names. Anthropic's reference devcontainer firewall works this way.
  • DNS filtering: the agent's name lookups are answered only for allowed names, so other names never resolve.
  • A proxy: the agent's HTTP and HTTPS traffic goes through a proxy that reads the requested host name and decides. Claude Code's built-in sandbox and Docker Sandboxes both route traffic through a proxy on the host.

02Why do IP-based allow-lists leak?

An address rule only knows addresses. Once registry.npmjs.org is resolved and its addresses are allowed, the firewall cannot tell a request to the registry from a request to any other site on the same content delivery network address. It also usually allows that address on every port and protocol, not only HTTPS on 443. And addresses resolved once at start go stale when the provider changes them.

The second leak is the rules around the list. Anthropic's reference init-firewall.sh, as published, drops other outbound traffic but allows DNS on UDP port 53 and SSH on TCP port 22 to any destination, so the agent can still talk to any DNS server in the world. That is convenient for development and it is exactly the channel the next section describes.

03How does DNS exfiltration work, and how do you close it?

DNS exfiltration needs no allowed host at all. The agent looks up a name such as <encoded-data>.attacker.example. Its resolver does not know the answer, so it asks the name servers for attacker.example, which the attacker runs, and they log the query. The data has left in the question. MITRE ATT&CK lists DNS as an application-layer protocol adversaries use precisely because it blends into normal traffic, and CVE-2025-55284 in Claude Code was this pattern: auto-approved commands such as ping and dig let an injected agent send a .env file out through lookups.

Closing it takes two steps. First, the sandbox must not be able to reach a resolver of its choosing: lookups are intercepted and answered by something you control. Second, that resolver must refuse names that are not on the list, rather than forwarding them. A wildcard such as *.example.com reopens a small version of the channel, because every name under it is forwarded to that domain's name servers, so only allow wildcards over domains you trust.

Some sandboxes remove the problem by not offering UDP. Claude Code's sandbox documentation says UDP, QUIC and ICMP cannot leave the sandbox, and Docker documents that its Sandboxes block outbound UDP unless an experimental setting is on.

04Proxy vs DNS filtering: what does each one see?

DNS filtering sees a name once, at lookup. After that it sees nothing, and a program that connects to a literal IP address never asks it at all, so it has to be paired with an address rule. A forward proxy sees the host name on every connection, in the CONNECT line for HTTPS or the URL for plain HTTP, which makes its decisions more precise. But unless it terminates TLS, it does not see the method, path or body of an HTTPS request, and it cannot check that the name inside the encrypted connection matches the name it was asked for.

Anthropic's sandboxing documentation spells out the consequence. Its proxy decides from the client-supplied host name without inspecting TLS, so code in the sandbox can potentially use domain fronting or similar techniques to reach hosts outside the allow-list. For stronger isolation it suggests a custom proxy that terminates TLS and inspects traffic, with its CA certificate installed in the sandbox. That buys content visibility at the cost of decrypting everything the agent sends, including credentials, inside your proxy.

05What is allowed-domain exfiltration, and how do you limit it?

This is the hole every allow-list keeps. If the agent can reach a host that accepts data, it can put data there: a gist on GitHub, a comment on an issue, a file in a storage bucket, a request body to any API. MITRE ATT&CK calls it exfiltration over a web service, and it is attractive to attackers because the destination is legitimate. Anthropic's documentation warns specifically that allowing broad domains such as github.com can create paths for data exfiltration, and Docker's notes that its default allowed domains include broad wildcards such as *.googleapis.com.

Nothing at the network layer fully closes this, because the traffic is shaped exactly like legitimate work. What helps is making the list short and specific, and reducing what the agent holds to send.

  • Allow exact host names for the APIs the task needs, not whole platforms or wildcards.
  • Leave out hosts that accept uploads or user content unless the task needs them.
  • Restrict methods and paths where your proxy can see them, which means plain HTTP or credential routes it terminates.
  • Keep secrets out of the agent's environment and give it one workspace folder, so there is less to send.

06What does an egress broker add to an allow-list?

An egress broker is a proxy that is also the only way out: the sandbox's address policy is deny, and every request has to name its destination to the broker. That gives you host-level decisions on every request rather than once at lookup, a port limit per host, a check that an allowed name does not resolve to a private or metadata address, and a log of what was allowed as well as what was refused. When the broker also holds API keys, it adds them after the request leaves, so the agent can call an API without being able to read its key.

It does not remove the limits above. HTTPS to an allowed host is still a tunnel the broker carries without opening, programs that ignore proxy settings simply reach nothing, and an allowed host that accepts uploads is still a way out. Treat a broker as the layer that makes the allow-list precise and auditable, then keep the list short.

Takeaways

  1. A domain allow-list controls destinations, not content; any allowed host that accepts data is a way out.
  2. IP-based rules admit every site on a shared address and often every port, and go stale when addresses change.
  3. DNS exfiltration needs no allowed host; close it by answering lookups yourself and refusing unlisted names.
  4. A proxy sees host names on every connection but not inside TLS unless it terminates it; domain fronting is a documented gap.
  5. Prefer exact host names to wildcards and whole platforms, and leave out hosts that accept uploads.
  6. An egress broker makes the list precise and logged and can hold keys, but cannot see inside HTTPS tunnels.

Where kosa8 fits

kosa8 enforces egress on the host, outside the agent's microVM. A sandbox created with an allow-list refuses everything else, and the network guard reads every frame the virtual machine sends before anything forwards it, so root inside the sandbox cannot remove the rule. DNS questions are intercepted and answered on the host: listed names are resolved by your computer's resolver, other names get REFUSED and are logged, and an allowed name that resolves to a private, loopback or link-local address is withheld. Brokered kits add an egress broker that admits hosts by name on ports 443 and 80, logs allowed and refused requests to the hash-chained audit log, and keeps API keys on the host. The kosa8 docs list the limits this post describes: an allowed address is reachable on every port under address rules, a wildcard lets data out through DNS, a CONNECT tunnel is opaque, and an allowed host that accepts uploads is a way out.

Check yourself · +100 XP

A sandbox allows only api.anthropic.com, but outbound DNS to any server is open. How can an injected agent still send a secret out?

Questions people ask

Is a domain allow-list enough to stop an AI agent exfiltrating data?

No. It limits where the agent can connect, not what it sends. Close DNS as a side channel, keep the list to exact host names, leave out hosts that accept uploads, and keep secrets out of the agent's environment.

What is the difference between proxy and DNS filtering for agents?

DNS filtering decides once, when a name is looked up, and misses connections to literal IP addresses. A proxy decides on every connection by host name, but without TLS termination it cannot see paths or bodies inside HTTPS.

How do I prevent DNS exfiltration from an AI agent sandbox?

Do not let the sandbox reach DNS servers of its choosing. Intercept lookups, answer only names on the allow-list, refuse the rest, and avoid wildcards over domains you do not control.

Sources

  1. Sandboxing — Claude Code docs
  2. init-firewall.sh (reference dev container) — anthropics/claude-code on GitHub
  3. Docker Sandboxes: security — Docker docs
  4. Application Layer Protocol: DNS (T1071.004) — MITRE ATT&CK
  5. Exfiltration Over Web Service (T1567) — MITRE ATT&CK
  6. Permissive default allowlist enables unauthorized file read and network exfiltration in Claude Code (CVE-2025-55284) — GitHub Security Advisory
  7. Claude Code: data exfiltration with DNS (CVE-2025-55284) — Embrace The Red (Johann Rehberger)
  8. Network rules — kosa8 docs
  9. Prompt injection meets your API keys: why the key should never enter the sandbox — kosa8 blog
  10. How do I restrict an AI agent's network access to an allow-list? — kosa8 guides

Written by the kosa8 team. Every kosa8 command was checked against the CLI, and every claim about another product links to that product's own documentation. Spotted a mistake? Tell us.

Try it on your own machine

Give your next agent its own sealed machine.

One line installs kosa8 on your own machine. Every feature, plans from $29 a month.