Fixed Exit Case Study: A Stolen Agent Token Reaches Nothing Its Policy Refuses, Even Sent Straight to the Exit
Partners often let traffic in by IP address: an API kept for one customer, a database behind an allowlist, an internal system that trusts only the office. For AI agents and CI jobs that means fixed addresses to leave from, and the usual answer is a proxy with a fixed address.
A plain proxy trusts whatever reaches it. If an agent’s machine is hijacked, or its token copied, the proxy forwards whatever the new owner asks for, from the trusted address. The policy the agent was meant to follow lives on the agent’s side, which is where the attacker now sits.
Exit, the fifth VPN Works engine, holds the policy at the far end too. Its demo replays a recorded run with two agents, two exits and a stolen token.

The Setup
Two agents run sealed under the Agent, and two exits stand in two “countries”, exit-de and exit-nl. A partner lets in four fixed addresses. Through exit-de, agent-1 always arrives from 198.51.100.10 and agent-2 from 198.51.100.11, whatever they ask for.
Each agent has a policy. The Agent checks it before anything leaves the machine, and the exit checks the same policy again before it connects anywhere.
Checked at Both Ends
agent-1 asks for attacker.test. Its policy refuses that, the Agent says no, and nothing leaves the machine.
Then it asks for intranet.partner.test. The policy allows the name, so the Agent sends the request on. At the exit the name resolves to 10.50.0.5, a private address, and the policy’s deny_private refuses it. When names resolve at the exit, the Agent never learns where they point, so this check can only happen there. The Agent passes the exit’s reason on to the program: “the exit refused it (deny_private): intranet.partner.test resolved to 10.50.0.5”.
The Stolen Token
Now a script holding agent-2’s token talks to exit-de directly. It skips the Agent and every check the Agent makes, and asks for the cloud metadata address, attacker.test and the partner’s intranet. All 3 are refused, and nothing reaches a server. The metadata address falls to deny_private, the other two to the policy’s default deny, and the exit’s record keeps each attempt with the rule that refused it.
The token still opens whatever agent-2’s policy allows: files.partner.test, and api.partner.test on port 80. Exit can’t tell a stolen token from its owner. It keeps the token inside the policy, and it keeps a record of the token’s use.
When an Exit Dies
3.3 seconds into the run, exit-de is killed. Each agent’s next connection gives up on it at once and opens through exit-nl, 5 and 9 ms after its dial began. No request fails. The partner now sees 203.0.113.10 and 203.0.113.11, so it has to allow both exits’ addresses for each agent. An exit that goes silent costs more than one that dies: the next connection waits out the 3-second limit before it moves.
One Record From Both Ends
Every connection that reached an exit is in two records, the Agent’s and the exit’s. Both carry the agent’s run ID and the connection’s number, and vpnw-exit join matches them. In the demo’s run, 9 of 9 joined. The request for attacker.test stopped at the Agent, so only the Agent recorded it. The stolen token’s 3 requests have no Agent run behind them at all, which is worth knowing on its own.
Is Any of It Real?
The run is real: the Agent and two exits, with real TLS, recorded in a private test network on one Linux machine. The countries, the partner and the attacker are stand-ins inside that private network, and the exits’ addresses come from the ranges set aside for documentation. The page replays the run, and Exit’s own code, compiled for the browser, decides the 12 recorded exit decisions again with the same rules.
In Exit’s tests, 110 of 110 requests got the same decision, rule and reason from the Agent and from an exit, under five policies. An exit added about 2 ms to each new connection, its TLS handshake included.
What It Doesn’t Do Yet
No exit has run on a real public address yet, and the tunnel to the exit is TLS, with WireGuard still to come. Exit 0.1.0 is an Alpha, tested on one Linux machine.
The demo runs in the browser on the Exit page, with nothing to install. The code is at github.com/VPNWorks/vpnw.