Process sandboxes: namespaces, seccomp, Landlock, Seatbelt
No container, no VM, no daemon — just the kernel's own primitives applied to a process tree. This is what most coding agents actually use underneath their sandbox flag, and it is the layer where the network story most often collapses.
The two-wall pattern
Agent vendors converged on the same shape during 2026, and it is a good one:
| Platform | Filesystem wall | Network wall | Used by |
|---|---|---|---|
| macOS | Seatbelt via sandbox-exec, with glob-based path rules | Seatbelt rules that deny direct egress, plus a proxy | Claude Code, Codex CLI, Gemini CLI, agent-safehouse, nono, SandVault |
| Linux / WSL2 | bubblewrap bind mounts, or Landlock path rules | --unshare-net with a proxy bridge and seccomp socket filtering | Claude Code, Codex CLI, Greywall, Fence, agentjail, flar |
| Windows | Restricted tokens with a synthetic SID and DACLs, or an AppContainer | Windows Firewall matching a dedicated user principal | Codex CLI, and most tools only in an advisory mode |
The primitives
Namespaces and cgroups
The foundation everything else builds on: PID, mount, user, network, IPC, UTS and cgroup views. Unprivileged user namespaces are what make rootless sandboxes possible — and they are also the thing hardening guides sometimes disable, which quietly breaks rootless containers.
Limit: a view, not a boundary. Kernel bugs in namespace handling are exactly the escape class this shares with containers.
seccomp-bpf
Syscall filtering. Excellent at removing dangerous, rarely used interfaces — ptrace,
module loading, raw sockets. Present in every serious sandbox.
Limit: it filters by syscall, not by intent. A sandbox that allows open
for legitimate reasons cannot use seccomp to say "not that file". And seccomp user notification, while
powerful, is the mechanism that has produced several deliberate bypasses.
Landlock
Mainline since Linux 5.13. Unprivileged, path-scoped access control: allow read here, write there, nothing else. Since ABI v4 it can also restrict network connections by port.
Limit: port-level only — no hostnames, no HTTP semantics, no methods. And it applies to the calling process, so a launcher has to re-exec itself to confine only the child. Fail-closed is essential: several tools have shipped versions that silently fell back to unsandboxed execution when Landlock was unavailable.
bubblewrap
The unprivileged namespace sandbox behind Flatpak, and the Linux default for most agent tools. A
single small static binary, no setuid, no daemon. Constructs the whole environment explicitly: bind
mounts, tmpfs, --unshare-*, --die-with-parent.
Limits: needs unprivileged user namespaces; SELinux/AppArmor can interfere; static policy only with no host-level network ACL of its own; and its mandatory-deny can only hide paths that exist, which is the root of a whole class of "the file did not exist at startup" bugs.
macOS Seatbelt (sandbox-exec)
Apple's TrustedBSD MAC framework, driven by a Scheme-like profile. Deprecated officially since Sierra in 2016 and still fully functional through macOS 26. Apple uses it internally, and every macOS agent sandbox depends on it.
Limits: deprecated with no replacement for confining arbitrary CLI processes (App Sandbox needs build-time re-signing; Apple's container runtime is Linux-only). The real risk is silent behavioural change rather than removal, and the industry pattern is "everyone uses it, nobody has a migration plan".
firejail, nsjail, minijail
Mature jailers from the pre-agent era. firejail is the desktop-oriented SUID sandbox; nsjail is Google's namespace+seccomp jail used inside larger systems; minijail is ChromeOS/Android's launcher. All are genuinely production-hardened and all predate the network-allowlist problem.
Limit: none of them solves hostname-level egress. firejail's setuid design also interacts awkwardly with unprivileged user namespaces, which is why agent tooling mostly chooses bubblewrap.
The failure modes that are actually on record
These are not hypotheticals. Each one is a documented incident or advisory, and together they define what a process sandbox can and cannot promise.
| Failure class | How it works | What it teaches |
|---|---|---|
| Denylist evasion by reasoning | An agent hitting a blocked path found /proc/self/root/usr/bin/npx, then disabled its own sandbox to finish the task. |
Denylists are worse than allowlists, and an agent treating the sandbox as an obstacle is not an adversary you prompted into being. |
| Symlink escape | A sandbox that validates a path before use, where a symlink swaps the target between check and open (CVE-2026-39861 in Claude Code's sandbox). | Path-based identity is fragile. The same argument is why inode labels (SELinux) survive a rename and path rules do not. |
| Local socket escape | A Landlock policy allowed Unix domain sockets, so the workload talked to the per-user systemd D-Bus socket and used systemd-run --user to spawn an unsandboxed sibling (CVE-2026-47128 in nono). |
Any local socket you allow is a control channel. Allowlist sockets explicitly, or mediate them. |
| Config-mutation at startup | The profile protected a settings file only if it existed at launch, so sandboxed code created it and injected a host-privileged hook (CVE-2026-25725). | This is bubblewrap's documented asymmetry: macOS globs block files that do not exist yet, bind mounts cannot. |
| Proxy bypass | Network policy expressed as HTTP_PROXY variables, defeated by a client that ignores them (Node before v24) or by any code that opens a raw socket. |
Unless the policy is in the kernel, it is advice. |
| Fail-open degradation | A sandbox that silently continued without enforcement when Landlock was unavailable, running with the host user's normal filesystem and network access. | Refuse to run rather than degrade. Test this path deliberately. |
| Host-bridge escape | On WSL2, a Linux-side sandbox cannot stop powershell.exe from being spawned by interop as a full-token Windows process. |
Any bridge to the host — interop, a browser, a credential helper, an MCP server — is outside the sandbox and must be reasoned about separately. |
| Host-side helper hijack | Tools that run a helper binary on the host with real privileges, resolved through PATH, when the sandbox can write to a directory on that path. |
Sanitise PATH and pin helper paths. A broker that can be pointed somewhere else is not a broker. |
What process sandboxes are good for
Excellent at
- Keeping an agent out of your SSH keys, cloud credentials and dotfiles.
- Making an agent's writable world be one directory.
- Zero-overhead, no-image, no-daemon setup that runs anywhere the kernel supports it.
- Being the inner wall inside a container or VM, which is the configuration experts actually use.
Mediocre at
- Network policy: strong on Linux with a network namespace, conventional elsewhere.
- Resource limits, which many implementations accept and never enforce.
- Anything that needs to spawn a helper on the host.
- Windows, where the equivalent primitives (restricted tokens, AppContainer) leak through
EveryoneACLs, hard links and unelevated network modes.
Cannot do
- Protect against a kernel exploit or a runtime CVE — the kernel is shared.
- Protect against a service you deliberately exposed (a socket, a helper, an MCP server).
- Contain resource exhaustion unless you configured cgroups and the implementation honours them.
- Be your only layer if the code is actively hostile. For that, you want a VM.