trailofbits / trailofbits/coop
Restrict guest network egress (allowlist + offline lockdown)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 243
- Forks
- 13
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 30
Description
Restrict guest VM egress so a compromised or prompt-injected agent can't reach arbitrary endpoints. Two options, with deliberately different strength:
1. No route out (structural — the strong option)
For the offline / local-model case, don't filter egress — don't give the guest a routed path at all. The guest gets a non-routed interface only:
- model in-guest: the agent reaches it over loopback; the VM has no external NIC (or the NIC has no default route). Simplest and airtight, but the VM needs the resources to run the model.
- model on the host: a host-local link with no default route / no NAT, so the agent can reach the local endpoint but has no path to the internet. Lets the model use host GPU/Metal (matters on Apple Silicon).
This is not a boundary inside the VM — it is the absence of a route. There is nothing for guest root to flush (the NOPASSWD:ALL sudo below is irrelevant) and no filter to misconfigure. It closes the "communicate externally" leg of the lethal trifecta for that session, and unlike a filter it also defeats DNS tunneling, because there is no resolver path out. Pairs with coop model <instance> local (#343).
2. Allowlist (filter — the weaker option)
Only when the agent genuinely needs some egress (cloud model API, GitHub, Docker Hub, package registries). This is a filter, so it carries the usual filter gaps; use it when "no route out" isn't acceptable.
[network]
egress = "allowlist" # "open" | "allowlist" | "none"
allowed_hosts = ["api.anthropic.com", "github.com", "registry.npmjs.org"]
A sensible default allowlist should ship out of the box. egress = "none" selects option 1 (no route); egress = "allowlist" selects this one.
Enforcement must be host-side, never in-guest
The original plan was in-guest iptables, on the assumption that the agent runs as non-root ubuntu and cannot flush the rules. That assumption does not hold: the guest user has passwordless sudo (NOPASSWD:ALL in /etc/sudoers.d/<user>, set in scripts/guest/guest-config.sh:77 and src/lima.rs:1410), so a compromised agent in bypass mode can sudo iptables -F and remove any in-guest restriction. Any in-VM control is exactly the in-band protection coop exists to avoid. So if filtering is used at all, it lives where guest root can't reach it:
- Firecracker — the host owns the TAP device and routing/NAT (jailer + TAP networking). Apply policy on the host (iptables/nftables on the TAP/FORWARD path, or a restrictive NAT/route policy); guest root cannot touch it, and it closes the boot-window gap.
- Lima / macOS — networking goes through Virtualization.framework / vmnet (socket_vmnet). Host-side filtering needs macOS
pfor vmnet/bridge-level control; harder, and likely the limiting platform. Needs investigation. (Note: "no route out" is simpler to realize here than a host-side filter — drop the default route / don't NAT.)
Known limitations (option 2 only)
- CDN IP rotation: resolve-at-start may go stale for long-lived VMs.
- DNS tunneling: an allowed resolver can still exfiltrate data. Only option 1 (no route) avoids this.
Related: #343 (ease local-model use). The disposable VM remains the boundary coop leans on regardless of egress policy.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the guest privilege setup in scripts/guest/guest-config.sh:77 and src/lima.rs:1410, then trace the Firecracker TAP/routing path and the Lima/macOS networking path. Compare the proposed egress modes and determine where host-side enforcement or no-route networking can be applied. Done means the selected policy is implemented for the supported paths without relying on in-guest controls, with the limitations documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, rust
- Domain
- infrastructure, networking, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100