Back to Blog
Security

Why Egress Allowlists Are the First Line of Defense Against Agent Data Exfiltration

· 9 min read

By Yuki Tanaka

Most security reviews of AI agent deployments start with access controls: what data can the agent read, which credentials does it hold, what permissions does it have. Those are the right questions for an application with a fixed code path. For an AI agent, there is a prior question that matters more: where can the agent send data?

An agent with read access to your internal APIs and unrestricted outbound networking is, structurally, a capable data exfiltration tool. The agent does not need to be compromised in any traditional sense to behave this way. It only needs to receive instructions, at inference time, that direct it to include data in a request to a destination the attacker controls. This is the prompt injection plus exfiltration pattern, and it changes the egress threat model in ways that traditional network controls were not designed for.

How the Attack Pattern Actually Works

In a financial services context, the scenario looks like this. A platform team at a mid-size brokerage deploys an agent to handle client portfolio inquiries. The agent has read access to account positions, recent transactions, and a market data feed. It processes natural language queries and returns formatted answers. The code is reviewed, the database permissions are scoped, the team ships to production.

A few weeks later, a client submits a query containing embedded instructions: a block of text in the document being analyzed that tells the agent to include a summary of account transaction history in its next outbound request to an analytics endpoint the attacker controls. The agent processes the document, follows the instruction, and sends a POST request. It did not decide to exfiltrate data in any intentional sense. It executed an instruction the same way it executes any other, because instruction-following is what it is trained to do.

Three conditions enable this: an agent that reads external input, an agent with outbound network access, and the ability to reach attacker-controlled infrastructure. The first two are almost always true in production deployments. The third is what egress allowlists close.

Why Application-Layer URL Filtering Does Not Close the Gap

The natural first response when teams recognize this threat is to add URL validation inside the agent's code. Check outbound destinations against an allowlist before the HTTP request fires. This approach has one structural problem: the filtering code runs inside the agent's process, inside the trust boundary. It can be influenced by the same input data that is triggering the outbound request.

A prompt injection that targets the validation logic directly, or that formats the destination URL in a way that passes the filter syntactically but redirects to an attacker-controlled server, can defeat application-layer filtering. The control also assumes that every tool the agent uses runs its URL through the same validation path. As agents gain more tools and integrations over time, that assumption becomes harder to maintain.

Runtime egress enforcement works at a different layer. The enforcement mechanism sits outside the agent process, at the network level, and evaluates outbound connection attempts against a policy without any participation from the agent's code. The agent cannot inspect, modify, or negotiate with the enforcer, because the enforcer is not part of the agent's execution context. It intercepts connections at the OS network layer before any packet leaves the sandbox.

What an Effective Egress Policy Actually Enforces

A useful egress policy for an AI agent is not a flat list of allowed domain names. A domain name list can be bypassed by using the allowed domain as a proxy, by using numeric IP addresses instead of hostnames, or by encoding the destination so it satisfies the domain pattern but redirects traffic elsewhere. An effective policy has three specific properties.

The first is default deny. Every destination not explicitly listed in the policy is blocked. Adding a new integration requires an explicit policy update, which creates a natural review point. Novel exfiltration attempts fail automatically because the destination is not in the policy. This is the most important single property: an allowlist that has no default position is not an allowlist.

The second is IP-layer enforcement in addition to DNS-name matching. DNS rebinding attacks and numeric IP addresses bypass hostname-only allowlists. An effective policy checks the resolved IP of the destination against an expected range and blocks the connection if the resolved address is outside that range, even if the hostname matches.

The third is protocol and port specificity. Allowing outbound connections to api.vendor.com for HTTPS on port 443 is not the same as allowing all traffic to that host. Allowing the hostname without specifying protocol and port leaves other channels open.

egress:
  default: deny
  allow:
    - host: "api.marketdata.internal"
      ports: [443]
      protocol: https
    - host: "reporting.brokeragecrm.internal"
      ports: [443]
      protocol: https
  deny_on_eval_error: true

The deny_on_eval_error flag is not optional. A policy that allows connections when the policy engine fails to evaluate them is not a security control. Evaluation failures should produce the same outcome as explicit denials.

Building the Allow Inventory Before Enforcing

One pattern that shows up reliably when teams first deploy egress controls: their agents contact more destinations than they expected. Telemetry SDKs that phone home. Third-party libraries that resolve configuration from remote endpoints at startup. Dependencies that perform license verification against external servers on the first run. None of these tend to be in the documentation anywhere useful.

The right sequence is to run in audit mode before switching to enforce mode. Audit mode records all outbound connection attempts without blocking them, producing a ground-truth inventory of what the agent actually contacts under production workload conditions. The allowlist is built from that inventory, not from what the team believes the agent does based on the code they wrote.

Running in audit mode for several days across representative workload patterns usually surfaces the complete destination set. It also surfaces surprises, which is the point. An allowlist built from assumptions has gaps. An allowlist built from observed traffic matches what the agent actually needs.

Handling Redirect Chains

One objection to strict egress allowlists is that some integrations use HTTP redirects. A REST API might respond with a Location header pointing to a different host. An agent that follows redirects automatically needs the policy to cover redirect destinations as well as initial request destinations, which can mean the effective destination set is larger than it looks from the source code.

Two approaches work in practice. The first is to trace the full redirect chain during the audit phase and add all intermediate and final destinations to the policy explicitly. This works well for integrations with stable redirect patterns that do not change frequently.

The second is to terminate redirect following at the enforcement layer. The enforcer proxies the redirect, checks the final destination against the policy, and returns the response to the agent only if the final destination is allowed. The agent issues one outbound request; the enforcer handles the chain. This produces cleaner policy semantics at the cost of marginally higher latency on first requests in redirect chains.

What Egress Allowlists Do Not Cover

This is worth stating directly: egress allowlists control where data can go. They do not control what data is included in requests to allowed destinations.

If an agent has legitimate permission to send requests to an internal CRM API and a prompt injection causes it to include sensitive account data in a request body that should contain only a session token, the egress enforcer allows that request. The destination is on the allowlist. The data leak happens within an allowed channel.

Egress allowlists close the "data sent to an attacker-controlled server" attack class completely. They do not close "data sent to a legitimate destination with more content than intended." That class requires output content validation at the application layer: field-level access controls, output redaction policies, or request body inspection at the enforcer layer. Each of these is a separate control addressing a different dimension of the same problem.

For financial services deployments, combining a default-deny egress policy with output content controls that constrain what fields the agent can include in outbound request bodies is the fuller answer. The egress policy handles the destination dimension. Content policies handle the payload dimension. Running both together, enforced at independent layers, is what a thorough security review will ask for.

Put these controls into production

Runta gives your agents sandbox isolation, resource quotas, configurable egress allowlists, and an immutable audit trail out of the box. No custom runtime engineering required.

Request Early Access Read the Docs