In the last post we gave the agent a disposable directory on the file system, but there is still a major security boundary at the network level. This post gives it a disposable network in the form of a squid proxy (Wikipedia), to address the threat model of exfiltration. A container housing agents (or the code they generate/install/otherwise run) with unrestricted web access can fire off POST requests exporting confidential data, and in the worst case this lets an opportunistic attacker prompt inject your session.
The first post deliberately simplified the idea of a ‘sandbox’ to be just about locking down the file system within the container, adding this layer brings it a step closer to having actual control.
The claude-container repo is a fork of the official Anthropic devcontainer remade for Podman, with some of the security features (including the init_firewall.sh script) removed. Once up and running, I removed some of the unused elements and replaced the firewall script with a proxy server.
Run with the restrictions on, we can't access the web:

With the --unrestricted-network flag, we can:

Setting boundaries by proxy
The constraint I wanted to express is that the Claude Code container may talk to Anthropic, and nothing else. To say that in iptables [IP packet filter rules for the Linux kernel firewall], you first have to enumerate Anthropic’s IP addresses, hence init-firewall.sh runs dig at container startup and freezes a name-to-address binding into an IP set. A proxy on the other hand sees the hostname, in the CONNECT line, so it enforces the same thing the policy is written about (there’s no translation step to go stale when the CDN rotates).
The firewall was set up to allow a VS Code IDE to run certain standard devtools commands (npm installs and git push operations). For this it exposes several routes out of the container that make it a poor ‘sandbox’, including NET_ADMIN and NET_RAW kernel capabilities (low level networking privileges for processes) and output TCP (port 22) and UDP (port 53) to all addresses. It permitted all GitHub address ranges, derives the host /24 from the default route and permits that subnet in both directions (meaning: allows communication with any device on the same local network as your gateway i.e. router), and adds carve outs for telemetry providers StatSig and Sentry.
All of that is patchable (close port 22, narrow GitHub ranges, etc) but the script still runs inside the container it confines! It needs root to do so, through a sudo call granting privilege to the container it confines so to speak (this was the part that confused me on first reading, given rootless setup is the point of podman).
Instead of giving the Claude Code container a route to the Internet and filtering it, here the container has no route out at all. It sits alone on an internal network called “caged”, which by construction cannot leave the host. A second, sibling container runs Squid and is attached to both the “caged” internal network and “egress” (a network which does reach the internet) on the other. Given that this container is the only path out, a single TCP port is all Claude Code can reach. Because of the separation of the two containers, there is no concern of Claude Code (or anything it runs) modifying the container’s own internet access rules in this design.
It is also convenient to debug since Squid logs all CONNECT calls, so the hosts that Claude reaches out to can be listed off (which is how the allowlist below was built, running a session with the gateway set permissively).
Internet
▲
│
┌────┴────┐
│ proxy │ egress network
└────▲────┘
│
┌────────┴────────┐
│ caged │ internal: true
│ Claude Code │ no default route
└─────────────────┘
Comparison to the native sandbox
In the time between the Anthropic devcontainer that became claude-container and now, Anthropic has released its own sandboxing runtime, which on Linux uses bubblewrap (Seatbelt on MacOS, apparently officially deprecated but still used). It restricts both the filesystem and filters the network using a proxy rather than a packet filter.
The difference with the current setup here is mainly in control over the isolation, as well as of Claude config and credentials, and control over npm installs, MCP servers, and build scripts (which run with partial isolation in the native sandbox, alongside Claude Code in userspace, but fully in the Podman container). Likewise the Claude Code installation on npm itself is fair game to isolate aggressively, given the supply chain attack frequency.
| Property | Native sandbox | Podman container |
|---|---|---|
| Bash subprocess isolation | yes | yes |
| Filesystem isolation | yes | yes |
| Network filtering | yes, per command | yes, whole container |
| The Claude Code process itself | not isolated | isolated |
| Claude config and credentials | on the host | in the container |
| npm install, MCP servers, build scripts | partly | fully |
| Kernel boundary | host kernel | host kernel |
| New attack surface added | small | container runtime |