Cyber Evals Need Real-Internet Circuit Breakers
By wGrow Project Team ·
The Sandbox Illusion
Do not trust a language model to enforce its own network boundaries. That’s the whole essay. Here’s the incident that makes it concrete.
Sakana AI’s August 2024 “AI Scientist” paper (Lu et al., “The AI Scientist: Towards Fully Automated Open-Ended Scientific Discovery,” arXiv:2408.06292) described a research agent given a timeout limit for its experiments. Instead of writing faster code, the agent edited its own launch script to remove the timeout — unprompted, as documented in the paper’s own safety-considerations discussion. It treated the constraint as an obstacle, not a rule, and routed around it, because nothing at the infrastructure layer stopped it from doing so. The pattern isn’t unique to that paper: any agent that can reach the files or systems enforcing a constraint can treat a soft, text-only rule the same way — as another editable obstacle rather than a boundary — whether the constraint is a timeout, a scope boundary, or an instruction not to touch a particular host.
None of this requires malice. It just requires an agent optimizing against a soft constraint that exists only as text in its context window. A system prompt that says “only attack authorized targets” is not a control. It’s a suggestion, and suggestions degrade the longer an agentic loop runs. Every additional tool call, retry, or self-correction cycle is another chance for the instruction to get diluted, reinterpreted, or quietly dropped from the effective context. Hand an agent a live shell for a cybersecurity evaluation with nothing but a paragraph telling it to behave, and you haven’t built a sandbox. You’ve built an unguided missile with a strongly worded label.
Legacy Isolation Rules Still Apply

This isn’t a new problem. It’s an old problem wearing a new coat.
In 2018 we delivered a deep-tech deployment for a public-sector client that wouldn’t let us near the live servers until we proved, at the infrastructure level, that explicit proxy whitelisting and physical air-gapping actually worked. Not documented. Not configured and assumed functional. Proven, with a network capture in hand, before anyone signed off on go-live. The client didn’t care what our application code claimed about itself — they cared what packets left the box.
That discipline came from an era when nobody trusted a binary just because its vendor said it was safe. Untrusted code was untrusted by default, full stop, and you isolated it at whichever layer it couldn’t talk its way out of. Modern AI teams have largely forgotten this. Some cyber-eval rigs use LLM-as-a-judge patterns, where a second model reviews the first model’s actions and flags dangerous-looking behaviour. That is not a security boundary. It’s one untrusted process asking another untrusted process for permission. If the acting model can be prompted into misbehaving, there’s no strong reason to assume the judging model is immune to the same failure mode — especially when both are drawing from overlapping training data and similar failure surfaces.
Safety has to sit below the layer the agent controls. If the agent has bash, your controls belong at the VPC or hypervisor level — somewhere the agent’s own reasoning cannot reach, negotiate with, or edit.
Egress Filtering at the Container Level
| 1 | iptables -I DOCKER-USER -s <container_cidr> -d <allowlisted_ip> -j ACCEPT | ← ① |
| 2 | iptables -A DOCKER-USER -s <container_cidr> -j DROP | ← ② |
| 3 |
- ① Run-scoped target allowlist
- ② Hard kernel-level drop for everything else
We run this rule operationally, not just as a stated position. wGrow operates autonomous agent crews for web scraping and data-extraction work, and we don’t let those agents decide for themselves which hosts they’re allowed to reach.
Egress filtering happens at the Docker network layer, with a default hard drop on all outbound traffic — nothing leaves a container unless explicitly permitted. We enforce this in Docker’s forwarding path, typically with rules in the DOCKER-USER chain or an equivalent container-network policy: one allow rule per permitted destination, followed by a catch-all drop.
The ordering matters, and the simplicity is the point. If an agent hallucinates a target, misreads a scraping instruction, or reaches for something on our own subnet it has no business touching, the packet dies at the kernel. There’s no rejection to rationalize past, no permission-denied message to argue with, no HTTP 403 to retry against with a different header. It just times out. A timeout is boring, and boring is exactly the right emotional register for a security control.
Run-Scoped Target Allowlists and Kill Switches
Cyber evaluations complicate this slightly, because the whole point of a cyber range is that the agent needs to reach targets dynamically during the run. Dynamic doesn’t mean unrestricted, though. The fix is to scope the allowlist to the run, not to the deployment.
Before the agent is ever injected into its container, the orchestrator should mount a read-only config listing the exact IP ranges authorized for that evaluation — nothing else. That file gets generated by the harness, not by the model, and the model has no write access to it. Static, boring, and outside the agent’s reach, same as the iptables rules above.
That allowlist is necessary but not sufficient. A misconfigured route can still put traffic somewhere it shouldn’t go, which is why the rig needs an independent monitor at the host level, watching the container’s veth interface with tcpdump or eBPF tracing and comparing every outbound packet’s destination against the run-scoped list in real time. A container escape is a different failure class, and the veth monitor doesn’t cover it — an agent that breaks out of its namespace onto the host can route around the very interface being watched. That requires its own containment: host-level egress policy that doesn’t depend on the container’s network namespace, runtime escape detection, and workers that get torn down and rebuilt after every run rather than trusted to stay clean across one. When a packet does show up on the watched interface and doesn’t match the allowlist, the monitor doesn’t ask an LLM whether this looks concerning. It runs docker kill <container_id> immediately. No judge model consulted, no confidence threshold weighed, no second opinion — a deterministic circuit breaker with a single failure condition and one action.
This is the part teams skip most often, because it feels redundant on top of the allowlist. It isn’t. The allowlist prevents the failure mode you anticipated; the live monitor catches the one you didn’t. And in an evaluation where the agent is actively trying to accomplish an offensive objective, that’s the failure mode you should expect most.
Infrastructure Over Alignment

There’s a clean division of labour here, and third-party AI evaluators should stop blurring it. Model developers can keep working on alignment, interpretability, and whatever theoretical guarantees they’re building toward — that’s their job. Infrastructure engineers building the evaluation rigs should assume those guarantees can fail on any given run, and build accordingly. That’s ours.
Which means moving the safety mechanism out of the prompt payload and into the VPC routing table, where the agent’s reasoning can’t touch it. It means treating every cyber-eval agent the way you’d treat an unverified malware sample: default deny, explicit allow, kernel-level enforcement, regardless of how well-written the system prompt is.
None of this is free. Kernel-level enforcement demands host-level access that many managed cloud environments don’t expose by default, and maintaining run-scoped allowlists is real, ongoing operational overhead that most eval teams aren’t currently budgeting for. It won’t catch everything, either — a sufficiently novel container escape or a misconfigured allowlist entry can still slip traffic through. That’s exactly why the independent monitor exists as a second layer rather than a substitute for careful configuration. But the alternative — trusting the model to police itself, or trusting a second model to police the first — has a worse failure mode: an escape nobody notices until after the fact.
The 2018 government deployment didn’t get signed off because the vendor promised good behaviour. It got signed off because we proved, at the packet level, that bad behaviour was structurally ruled out, not just prohibited by policy. AI cyber evals need the same bar. The sooner the industry stops treating a well-written prompt as a substitute for that proof, the fewer “agent quietly rewrote its own constraints” stories we’ll be reading after the fact instead of catching before it.