Name the private addresses an agent may live at - #213
Merged
Conversation
Refusing AGENT_COMPUTER_ALLOW_PRIVATE_HOSTS in production closed a hole and took something with it. Bring your own agent is a headline capability, a company's own agent legitimately lives at an internal address, and the only way to reach one was to lift the floor for everything. Telling people to set that flag is the advice that made it dangerous. AGENT_ENDPOINT_ALLOWED_HOSTS names addresses instead. A host, optionally with a port: agents.internal covers any port on that host, 10.0.0.42:9000 pins that one. Narrow on purpose, and each of these is a way it could have gone wrong. Agent endpoints only, so browsing is not widened. A page can steer a Bot somewhere; an operator naming an address they run is a different act from a Bot following a link to it. Exact matching, no wildcards and no suffixes. A pattern that widens by accident is the usual way a host check fails. A list written as URLs or with a star is refused at startup with the entry named, rather than quietly never matching. The never-allowed addresses stay never-allowed. Whether a refusal may be overruled is decided by re-running the check with the floor down, not by reading the refusal text: cloud metadata is refused before the private rule is reached, so naming it changes nothing. Every hop, not only the first. A named address is reachable wherever it appears and an unnamed one is refused wherever it appears, so a redirect cannot arrive somewhere registration would have declined. Unset means none, which is what every deployment has today.
davidmckayv
requested review from
MikeRyanDev,
guidovizoso and
tylerslaton
as code owners
August 24, 2026 02:42
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the gap #198 left behind.
Why
#198 was right to refuse
AGENT_COMPUTER_ALLOW_PRIVATE_HOSTSin production:.env.exampleshipped it on, the quick start says copy that file and deploy, and the image bakesNODE_ENV=production— so a by-the-book deployment ran with the private-address floor down.But it took something real with it. Bring your own agent is a headline capability, a company's own agent legitimately lives at an internal address, and after #198 the only way to reach one in the shipped image was to lift the floor for everything. Telling people to set that flag is precisely the advice that made it dangerous in the first place.
What
AGENT_ENDPOINT_ALLOWED_HOSTS— a comma-separated list of hosts, each optionally with a port:agents.internalcovers any port on that host.10.0.0.42:9000pins that one. A deployment sets this and leaves the floor exactly where #198 put it.Four ways this could have gone wrong, and what stops each
It could have widened browsing. It does not — agent endpoints only. A page can steer a Bot somewhere it should not go; an operator naming an address they themselves run is a different act, and the two do not deserve the same permission.
A pattern could widen by accident. There are no patterns. Matching is exact on the host as written. A list containing a
*, or written as URLs, is refused at startup with the offending entry named, rather than silently never matching and being discovered at the first registration.Cloud metadata could be named back in. It cannot. Whether a refusal may be overruled is decided by re-running the check with the floor down and seeing whether it passes — so "refused for being private" is separated from "refused for being the metadata address or not a web address" structurally, rather than by pattern-matching the refusal text, which would break the first time somebody rephrased it.
A redirect could be the way around registration. It is not. The list is carried to every hop, so a named address is reachable wherever it appears and an unnamed one is refused wherever it appears.
checkAgentEndpointis the single chokepoint for registration, the Test button and every redirect hop, so there is one place to get this right.Unset means none, which is what every deployment has today.
Proof
Driven in the browser, in production posture —
NODE_ENV=production,AGENT_COMPUTER_ALLOW_PRIVATE_HOSTS=false, one host named. Two addresses on the same LAN host, differing only by port:http://10.0.0.75:4900/ag-ui(not named)http://10.0.0.75:4899/ag-ui(named)The second one was dialled. The only complaint is about what came back, which is the point: the floor let it through because the operator named it, and the stub I pointed it at is not an AG-UI agent.
Tests: 19 new. The allowlist cases, the port-pinning both ways, the config parser including both refusals, and three redirect cases — a hop to a named address is followed, a hop to an unnamed one is refused, and a hop to the metadata address is refused even when someone has explicitly named it.
Full suite 1387 pass, 0 fail. Typecheck, lint and format clean.
Note
AGENT_COMPUTER_ALLOW_PRIVATE_HOSTSis unchanged and still refused in production. This does not reopen it; it removes the reason anybody had to reach for it.