Why Sandboxing Matters
Imagine this scenario. You ask an AI coding agent to clean up some temp files. The agent, confident in its interpretation, generates a command:
# The AI's "helpful" suggestion
rm -rf /
Without a sandbox, that command executes directly on your machine. Your files, your OS, your entire system — gone. With a sandbox, the command runs inside a contained environment. It can only see what you allow it to see. It can only touch what you explicitly permit.
Codex CLI treats every AI-generated command as untrusted by default. Even in "full auto" mode, the sandbox ensures that the blast radius of any single command is tightly bounded. The vault is not optional — it is structural.
The ExecPolicy DSL
Before any command even reaches the sandbox, it passes through the ExecPolicy — a domain-specific language that defines rules for what commands are allowed, which need human approval, and which are outright forbidden.
Three rule types form the vocabulary:
type ExecPolicy = {
prefix_rule: { // Matches command prefixes
prefix: "npm ",
decision: "allowed"
},
exact_rule: { // Matches exact commands
command: "rm -rf /",
decision: "forbidden"
},
network_rule: { // Controls network access
host: "registry.npmjs.org",
decision: "allowed"
}
}
Each rule maps a pattern to one of three decisions: allowed, prompt, or forbidden. The policy engine evaluates them top-to-bottom, first match wins. Here's what a real policy might look like:
The ExecPolicy DSL is declarative, not imperative. You describe what is allowed, not how to allow it. This makes policies auditable, version-controllable, and easy to reason about.
The Three-Tier Approval Flow
Every command the AI generates passes through a three-stage gate before it can execute. This is not a single check — it's a pipeline, and each stage can halt the command entirely.
Generated
Check
Approval
Execution
If the ExecPolicy says allowed, the command proceeds directly to sandbox execution. If it says prompt, the user sees a confirmation dialog with the exact command and can approve or reject. If it says forbidden, the command is silently dropped — the AI receives an error and must try a different approach.
Linux Sandboxing: Three-Layer Cake
On Linux, Codex CLI builds the strongest sandbox using three independent, overlapping security mechanisms. Each layer defends against a different class of escape. Click each layer to explore.
Bubblewrap creates a new mount namespace, PID namespace, and network namespace. The sandboxed process sees a carefully curated filesystem — only the project directory is bind-mounted read-write. System directories are either read-only or invisible.
bwrap \
--ro-bind /usr /usr \
--ro-bind /lib /lib \
--bind $PROJECT_DIR $PROJECT_DIR \
--tmpfs /tmp \
--dev /dev \
--unshare-pid \
--unshare-net \
--die-with-parent \
-- $COMMAND
Even inside the namespace, the process could attempt dangerous syscalls. Seccomp attaches a BPF (Berkeley Packet Filter) program to the process that intercepts every system call before it reaches the kernel. Only an explicit allowlist of syscalls passes through.
// Simplified BPF filter logic
if (syscall == SYS_read) ALLOW;
if (syscall == SYS_write) ALLOW;
if (syscall == SYS_open) ALLOW;
if (syscall == SYS_close) ALLOW;
if (syscall == SYS_ptrace) KILL;
if (syscall == SYS_mount) KILL;
default: ERRNO(EPERM);
Landlock is a Linux Security Module that provides unprivileged, stackable filesystem sandboxing. Combined with no_new_privs, the process cannot gain additional capabilities — even through setuid binaries or kernel exploits that escalate within namespaces.
// Landlock ruleset: restrict to project dir
struct landlock_ruleset_attr attr = {
.handled_access_fs =
LANDLOCK_ACCESS_FS_READ_FILE |
LANDLOCK_ACCESS_FS_WRITE_FILE |
LANDLOCK_ACCESS_FS_EXECUTE
};
landlock_create_ruleset(&attr, sizeof(attr), 0);
// Add rule: allow access to project dir only
landlock_add_rule(fd, LANDLOCK_RULE_PATH_BENEATH,
&(struct landlock_path_beneath_attr){
.allowed_access = FULL_ACCESS,
.parent_fd = open("$PROJECT_DIR", O_PATH)
}, 0);
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
Any single layer can be theoretically bypassed. But escaping all three simultaneously — namespaces, syscall filters, and LSM policies — is astronomically harder. This is defense in depth applied to AI command execution.
macOS Sandboxing: Seatbelt
On macOS, Linux namespaces don't exist. Instead, Codex CLI leverages Apple's Seatbelt framework — the same sandbox technology that powers the Mac App Store's security model. Seatbelt uses capability-based profiles written in a Lisp-like syntax.
;; Generated sandbox profile for Codex CLI
(version 1)
(deny default) ;; Deny everything by default
(allow process-exec) ;; Allow executing the command
(allow file-read*
(subpath "/usr/lib")
(subpath "/usr/bin")
(subpath "/System"))
(allow file-read* file-write*
(subpath "$PROJECT_DIR"))
(deny network*) ;; No network unless allow-listed
(allow network-outbound
(remote tcp "registry.npmjs.org:443"))
The key insight: these profiles are generated on the fly. When the ExecPolicy allows network access to specific hosts, the Seatbelt profile generator dynamically adds those hosts. The profile is written to a temp file and passed to sandbox-exec at spawn time.
Windows Sandboxing
Windows takes a fundamentally different approach. Rather than namespaces or profiles, it relies on the combination of three native security mechanisms working in concert.
Platform Comparison
Each platform reaches the same security goal — containment — through entirely different mechanisms. Here's a side-by-side view.
Linux: Namespace + Syscall + LSM
The gold standard. Three independent layers that each restrict a different dimension of the attack surface.
bwrap --unshare-all --ro-bind / / \
--bind $PWD $PWD --seccomp 3 -- sh -c "$CMD"
macOS: Seatbelt Profiles
Apple's capability-based sandbox. A deny-default Lisp profile is generated dynamically and passed to sandbox-exec.
sandbox-exec -f /tmp/codex-profile.sb \
sh -c "$CMD"
Windows: Tokens + ACLs + ConPTY
Windows uses its native security model. Restricted tokens strip privileges, ACLs gate filesystem access, and ConPTY controls I/O.
CreateProcessAsUser(restrictedToken,
NULL, cmdLine, ..., CREATE_NEW_CONSOLE,
NULL, projectDir, &si, &pi);
Network Sandboxing
Network access is the most dangerous capability to grant. A compromised process with network access can exfiltrate data, download malware, or establish reverse shells. Codex CLI treats network access with the same rigor as filesystem access, using platform-specific mechanisms.
Cross-Platform Network Control
- Linux: Network namespace isolation via
--unshare-net. When network is needed, iptables rules whitelist specific hosts/ports. - macOS: Seatbelt
network-outboundrules in the generated profile. Deny-default for all network, explicit allows per host. - Windows: Windows Firewall rules scoped to the process.
netshcommands configure per-process outbound rules.
Blocking the cloud metadata endpoint (169.254.169.254) is critical. A compromised process running on AWS/GCP/Azure could steal instance credentials and pivot to cloud resources. The vault blocks this by default on all platforms.
The Vault in Action
Let's trace a real command — npm install express — through the entire vault. Click "Run Trace" to watch the command flow through every security layer.
npm install expressprefix_rule("npm ") → decision: allowedregistry.npmjs.org:443 → allowed$PROJECT_DIR/node_modules is in the allowed write pathThe entire flow is invisible to the user in normal operation. When everything is allowed, it feels like running commands directly. The vault's power is in what it prevents — the commands that never escape, the network calls that never connect, the files that remain untouched.