04
Anatomy of an AI Coding Agent — Part 4 of 8

The VaultHow Every Command Runs in a Sandbox

The AI wants to run code on your machine. Here's the multi-layered fortress that decides what's allowed, what needs approval, and what gets locked away forever.

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.

Without Sandbox
$ rm -rf /
Filesystem wiped
OS destroyed
Data unrecoverable
The command runs with full user privileges. No guardrails, no questions asked. Catastrophic failure.
With Sandbox
$ rm -rf / # denied
Operation blocked
Only /tmp visible
Host untouched
The command is confined to a restricted namespace. It sees only bind-mounted directories and can't escape.
Design Philosophy

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:

exec-policy.json
prefix git status allowed
prefix npm install allowed
prefix cargo build allowed
exact rm -rf / forbidden
exact curl | bash forbidden
prefix docker run prompt
network registry.npmjs.org:443 allowed
network *:* forbidden
Key Insight

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.

Stage 1
Command
Generated
Stage 2
ExecPolicy
Check
Stage 3
Human
Approval
Execute
Sandbox
Execution
ALLOW → Run
PROMPT → Ask User
DENY → Block

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.

1
Bubblewrap (bwrap)
Filesystem isolation via namespaces

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
mount namespace PID namespace bind mounts read-only rootfs tmpfs /tmp
2
Seccomp-BPF
System call filtering at kernel level

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);
BPF bytecode syscall allowlist SECCOMP_SET_MODE_FILTER kernel enforcement
3
Landlock + no_new_privs
LSM-based fine-grained access control

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);
Landlock LSM no_new_privs unprivileged stackable setuid immune
Defense in Depth

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.

ACLs (Access Control Lists)
Windows NTFS ACLs restrict which files and directories the sandboxed process can read, write, or execute. Permissions are set at the filesystem level before the process spawns.
Restricted Tokens
The process runs under a restricted security token with stripped privileges. SIDs are marked as deny-only, removing access to resources the full user token could reach.
ConPTY
The Console Pseudo-Terminal provides a controlled I/O channel. Codex CLI captures all output through ConPTY, preventing the sandboxed process from directly manipulating the console.

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.

Bubblewrap
Mount, PID, and network namespaces. Bind-mount project dir read-write, everything else read-only or hidden.
Seccomp-BPF
Kernel-level syscall allowlist. Blocks ptrace, mount, reboot, and other dangerous calls.
Landlock
LSM filesystem restriction that survives privilege escalation. Combined with no_new_privs.
Spawn command
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
Runs the process under a Seatbelt profile. Deny-default with explicit allows for file paths and network hosts.
Dynamic Profiles
Generated at runtime based on ExecPolicy. Network rules map directly to Seatbelt network-outbound allows.
Capability Model
Processes declare what they need. Everything else is denied. No root required to apply restrictions.
Spawn command
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.

Restricted Tokens
CreateRestrictedToken strips SIDs and privileges. The process runs with the minimum viable access level.
NTFS ACLs
Set before process spawn. Only project directory and essential system paths are accessible.
ConPTY
Pseudo-terminal captures all I/O. The process cannot escape its controlled console environment.
Spawn approach
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-outbound rules in the generated profile. Deny-default for all network, explicit allows per host.
  • Windows: Windows Firewall rules scoped to the process. netsh commands configure per-process outbound rules.
registry.npmjs.org:443
npm package downloads
github.com:443
Git operations over HTTPS
evil-server.com:4444
Reverse shell attempt blocked
*:21 (FTP)
Unencrypted data transfer blocked
pypi.org:443
Python package index
169.254.169.254
Cloud metadata endpoint blocked
Security Note

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 express
1
AI generates command
The model outputs: npm install express
2
ExecPolicy lookup
Matches prefix_rule("npm ") → decision: allowed
3
Network policy check
npm needs registry.npmjs.org:443allowed
4
Sandbox profile generated
Seatbelt/bwrap profile created with project dir RW + npm registry network access
5
Process spawned in sandbox
Child process runs under restricted profile, PID-namespaced, syscall-filtered
6
npm resolves dependencies
Network calls to registry.npmjs.org succeed. Calls to other hosts are blocked.
7
Packages written to node_modules/
Write succeeds — $PROJECT_DIR/node_modules is in the allowed write path
8
Exit code captured, sandbox torn down
Process exits 0. Namespaces destroyed. Result returned to the AI agent.

The 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.

Key Takeaways

ExecPolicy DSL provides a declarative, auditable way to define what commands and network calls are allowed before execution.
Three-tier approval ensures every command passes through policy check, optional human review, and sandboxed execution.
Linux uses three layers: Bubblewrap namespaces, Seccomp-BPF syscall filtering, and Landlock LSM — defense in depth.
macOS uses Seatbelt with dynamically generated Lisp profiles, providing capability-based isolation.
Windows combines restricted tokens, NTFS ACLs, and ConPTY to achieve equivalent containment.
Network sandboxing blocks all outbound traffic by default, whitelisting only policy-approved hosts and ports.
← Prev: The Brain Article 4 of 8 Next: Four Windows →