skip to content

How do you stop an agent's HTTP tool from becoming an exfiltration path?

level: seniorimportance: should knowfreq 48%

answer

  1. take an id, not a URL
  2. default-deny, then add hostnames
  3. enforce at name resolution, not just sockets
  4. redirects walk off the allowlist
  5. size and rate limits bound, do not prevent

basics

~20 s

Remove the model's control over the destination. Have tools take an identifier and build the URL server-side, run the tool runtime with default-deny network egress and an allowlist of approved hostnames, refuse cross-host redirects, and cap outbound body size and rate.

solid answer

~50 s

A tool signature of fetch(url) hands the model an unrestricted egress channel, so the first move is to shrink the parameter: take a document id, a customer reference or an enum of endpoints, and construct the request server-side from an approved base URL. Where a genuinely open fetch is required, put the control below the tool. Run the tool runtime with default-deny egress and an allowlist of approved hostnames, ideally enforced at name resolution so that a request to an unapproved pastebin dies before a socket opens, and route the rest through a forward proxy that re-checks the host on every hop and refuses redirects that leave the allowlist. Then bound the channel: limit request body and query size, rate-limit outbound calls per session, and log the full destination. The allowlist is the control; logging and limits only shape what an approved destination can carry.

code

python · 11 lines
python
from urllib.parse import urlsplit

ALLOWED_HOSTS = {"api.partner.example", "docs.internal.example"}

def check_destination(url: str) -> str:
    parts = urlsplit(url)
    if parts.scheme != "https":
        raise ValueError("scheme not allowed")
    if parts.hostname not in ALLOWED_HOSTS:
        raise ValueError("host not allowed: " + str(parts.hostname))
    return url

go deeper

for a junior

Know that a tool which lets the model pick any URL is an open export path, and that the safer shape is a tool that takes an identifier and builds the request itself.

for a middle

Explain default-deny egress with a hostname allowlist, why enforcing at name resolution matters, and why size and rate limits bound the channel rather than closing it.

for a senior

Show you would design the tool signature first, put the allowlist below the tool where the model cannot reach it, handle redirects explicitly, and alert on denials as a detection signal.

for a principal

Own the policy that no agent runtime gets default outbound access, and be able to state plainly what residual egress remains after the network control and why other layers must cover it.

## The shape of the problem Give an agent a tool that performs an HTTP request to a model-chosen URL, and you have given whoever can influence the model a general-purpose data-export API. Nothing else in the system has to be broken. The tool does exactly what it was built to do, with a destination the model selected and a body or query string the model composed. This is the most direct egress channel an agent has, and it is also the easiest one to design away. ## Control one: shrink the parameter The strongest fix is not a filter but a signature change. Ask what the tool actually needs to express. A tool that fetches a knowledge-base article needs an article id, not a URL. A tool that calls a partner pricing API needs a listing reference and maybe an enum selecting which of three endpoints to hit. In both cases the server holds the base URL and constructs the request; the model contributes a value that is validated against a known set. The egress destination is then a property of your code, not of the model's output, and no amount of injected instruction can move it. This is worth pushing on harder than teams usually do, because open-ended fetch tools are often added for convenience during prototyping and never narrowed. When a reviewer sees a tool whose parameter is a full URL, the first question should be whether the model needs to choose the host at all. ## Control two: default-deny network egress Sometimes an open fetch is the product, as with a research agent that browses. Then the control moves below the tool, into the environment the tool runs in. Default-deny is the posture: the tool runtime can reach nothing by default, and specific destinations are added deliberately. Enforcing at name resolution is particularly effective because it is early and cheap. In a runtime where only approved API hostnames resolve, a request to an unapproved pastebin fails at resolution: no connection is attempted, no bytes leave, and critically the DNS query itself never reaches an attacker-controlled zone. That last point matters because resolution is itself an egress channel; a network policy that blocks TCP to unapproved hosts but forwards all DNS still leaks through hostname labels. A forward proxy complements this. It gives you one place that sees the fully assembled request, can enforce the host allowlist per hop, can strip credentials that should not travel outward, and can log destinations for detection. It also lets you make an explicit decision about redirects, which is where allowlists usually break: an approved host answering with a redirect to an unapproved one moves the request off the list. The proxy must re-evaluate the allowlist on the new host and refuse rather than follow. The same reasoning applies to approved hosts that relay by design, such as shorteners and open image proxies, which should not be on the list at all. ## Control three: bound the channel Even within the allowlist, an approved destination can carry more than intended. Bounding is cheap: limit the size of query strings and request bodies the tool may send, rate-limit outbound calls per session, and reject requests whose parameters are implausibly large for the tool's purpose. These do not stop a determined small leak, and it is important to say so honestly in an interview. A credential or a price fits in a hundred bytes and will pass any reasonable size limit. Bounding raises the cost of bulk copying and produces a detectable signal; the allowlist is what actually constrains the destination. ## Detection alongside prevention Log the resolved destination, not just the tool name, for every outbound call, and alert on denials rather than treating them as noise. A spike of blocked resolutions from one session is the clearest signal available that something is trying to leave, and it is only visible if denial is logged as an event. Ideally the log records which session and which retrieved documents were in context at the time, so an investigation can trace the influence backwards. ## Where this control ends Network egress policy constrains the tool runtime. It does not constrain what the model writes into a response that a person then reads, nor what an approved integration does with the data once it legitimately receives it. It also cannot distinguish an intended call to an approved API from an unintended one carrying extra data in an approved parameter. Those residual paths are why egress control sits alongside output-sink allowlisting and retrieval scoping rather than replacing them, and why an interviewer will usually follow up by asking what is still open after the allowlist is in place.

  • Your proxy allowlists hosts but follows redirects transparently. What is the gap?
    An approved host that returns a redirect can send the request to an unapproved one, and the payload travels with it. The allowlist is only meaningful if it is evaluated on every hop, so the proxy must re-check the host after each redirect and refuse rather than follow. The same reasoning excludes shorteners and open proxies from the list entirely, since relaying is their purpose.
  • Does rate limiting outbound tool calls meaningfully reduce exfiltration risk?
    It reduces bulk copying and creates a detectable signal, but it does not protect the secrets that matter most. An API key or a price fits in a single small request that no plausible limit would block. Treat limits and logging as detection and blast-radius controls layered on top of destination allowlisting, never as the primary defence.
  • What remains open after default-deny egress is in place?
    Anything that does not travel through the tool runtime: text the model writes into a response a human reads and forwards, data an approved integration legitimately receives and then re-shares, extra data smuggled inside a legitimate parameter to an approved API, and the trace store that copies the whole context. That residue is why egress policy sits beside output-sink allowlisting and retrieval scoping rather than replacing them.

saying these in an interview costs you the question

  • Leaving a tool signature that accepts an arbitrary URL
  • Blocking outbound TCP while forwarding all DNS queries
  • Following redirects without re-checking the host allowlist
  • Treating request-size limits as a substitute for a destination allowlist
  • Allowlisting a shortener or open proxy that relays onward

context