This page documents the implementation of Codex's sandboxing system, which provides platform-specific process isolation by wrapping commands with OS-specific sandbox mechanisms. The system transforms high-level SandboxPolicy specifications into platform-specific sandbox wrappers (Seatbelt on macOS, Landlock+seccomp on Linux, Restricted Token on Windows) or no sandboxing (SandboxType::None).
For approval policy integration, see page 5.5. For the overall tool execution pipeline, see page 5.3.
The sandboxing implementation consists of three layers:
SandboxPolicy enum defined in the protocol (ReadOnly, WorkspaceWrite, DangerFullAccess, ExternalSandbox).git protectionSandboxType selection and command wrappingCore Data Flow:
Sources: codex-rs/protocol/src/protocol.rs379-426 codex-rs/protocol/src/protocol.rs433-457
The SandboxPolicy enum is defined in protocol.rs and represents the high-level security policy:
| Variant | File Access | Network | Writable Roots |
|---|---|---|---|
DangerFullAccess | Unrestricted | Enabled | N/A (no sandbox) |
ReadOnly | Read-only everywhere | Disabled | Empty |
ExternalSandbox | Full (assumes external sandbox) | Configurable | Empty |
WorkspaceWrite | Read everywhere, write in computed roots | Configurable | Computed via get_writable_roots_with_cwd() |
Key Methods:
has_full_disk_read_access() - Always returns true (read access not restricted)has_full_disk_write_access() - Returns true for DangerFullAccess and ExternalSandboxhas_full_network_access() - Checks policy variant and network_access fieldget_writable_roots_with_cwd(cwd) - Computes Vec<WritableRoot> for the given working directorySources: codex-rs/protocol/src/protocol.rs379-426 codex-rs/protocol/src/protocol.rs486-622
The get_writable_roots_with_cwd() method computes which directories are writable under WorkspaceWrite policy, including special subpaths that must remain read-only even when the root is writable.
Computation Algorithm:
Default Writable Roots (for WorkspaceWrite):
cwd): Always included/tmp (Unix): Included unless exclude_slash_tmp = true$TMPDIR: Included unless exclude_tmpdir_env_var = truewritable_roots: From config, always includedExclusion Flags:
exclude_slash_tmp: When true, do not include /tmp in writable roots (Linux/macOS)exclude_tmpdir_env_var: When true, do not include $TMPDIR in writable rootsSources: codex-rs/protocol/src/protocol.rs511-622
A critical security feature is preventing the agent from modifying .git directories, which could allow privilege escalation (e.g., modifying .git/hooks). The get_writable_roots_with_cwd() method automatically identifies .git directories and adds them to read_only_subpaths.
Protection Logic:
Cases Handled:
Directory .git: Standard repository
root/.git to read_only_subpathsFile .git: Git worktree or submodule
gitdir: <path> pointer, resolve path, add both the file and resolved directory to read_only_subpaths.git contains gitdir: ../.git/modules/mysubmoduleNo .git: Not a git repository
Additional Protected Paths:
.agents/ directory (if exists): Prevents modification of agent skills.codex/ directory (if exists): Prevents modification of Codex configurationHelper Functions:
is_git_pointer_file(path) - Checks if path is a file named .gitresolve_gitdir_from_file(dot_git) - Parses gitdir: line and resolves the pathSources: codex-rs/protocol/src/protocol.rs575-611 codex-rs/protocol/src/protocol.rs624-679
The WritableRoot struct encapsulates a writable root directory and its read-only subpaths:
Method: is_path_writable(path)
Determines if a given path is writable under this WritableRoot:
path starts with root - if not, return falsesubpath in read_only_subpaths:
path starts with subpath, return falsetrueThis allows the sandbox to grant write access to a root directory while carving out read-only exceptions for sensitive subdirectories.
Sources: codex-rs/protocol/src/protocol.rs433-457
Implementation: create_seatbelt_command_args() generates Sandbox Profile Language (SBPL) and wraps the command with /usr/bin/sandbox-exec.
Environment Variables Set:
CODEX_SANDBOX=seatbeltCODEX_SANDBOX_NETWORK_DISABLED=1 (if network disabled)Debug Command:
The --log-denials flag captures sandbox violations via log stream for debugging.
Sources: codex-rs/cli/src/lib.rs9-24
Implementation: Codex vendors a modified version of bubblewrap (a setuid sandbox) to provide robust process isolation on Linux. The implementation consists of two parts: vendored C sources compiled at build time and a Rust wrapper that exposes the bwrap_main function.
Build-Time Compilation:
The codex-rs/linux-sandbox/build.rs script compiles bubblewrap's C sources and links them with the Rust binary:
Required Build Dependencies:
| Dependency | Purpose | Detection Method |
|---|---|---|
libcap-dev | Capability management | pkg-config |
gcc / clang | C compiler | Standard toolchain |
pkg-config | Dependency detection | System package |
FFI Wrapper:
The codex-rs/linux-sandbox/src/vendored_bwrap.rs module provides a safe Rust interface to the vendored bubblewrap:
Sandbox Arguments:
Bubblewrap is invoked with arguments that specify mount points, capabilities, and namespaces:
| Argument Pattern | Purpose | Example |
|---|---|---|
--ro-bind SRC DST | Read-only bind mount | --ro-bind / / |
--bind SRC DST | Writable bind mount | --bind /workspace /workspace |
--tmpfs PATH | Temporary filesystem | --tmpfs /tmp |
--unshare-net | Disable network namespace | Applied when network disabled |
--cap-drop ALL | Drop all capabilities | Security hardening |
--new-session | New session ID | Process isolation |
Debug Command:
Fallback Behavior:
If vendored bubblewrap is unavailable (non-Linux platforms or build failure), the cfg(vendored_bwrap_available) guard causes the sandbox to fall back to SandboxType::None.
Sources: codex-rs/linux-sandbox/build.rs1-120 codex-rs/linux-sandbox/src/vendored_bwrap.rs1-60 codex-rs/linux-sandbox/config.h1-4 .github/workflows/rust-release.yml110-116
Implementation: In-process sandboxing via codex-windows-sandbox crate using Windows Restricted Token API.
Feature Flags:
Feature::WindowsSandbox - Enables standard restricted token sandbox (experimental)Feature::WindowsSandboxElevated - Enables two-phase elevated sandbox (experimental)Both features are currently in UnderDevelopment stage and disabled by default.
Debug Command:
Sources: codex-rs/core/src/features.rs479-489 codex-rs/cli/src/lib.rs40-52
The SandboxType enum represents the actual platform-specific sandbox mechanism to use:
Selection Logic (get_platform_sandbox):
SandboxManager::select_initial() Method:
SandboxablePreference Values:
Forbid - Tool cannot be sandboxed (e.g., apply_patch needs direct file access)Require - Tool must be sandboxedAuto - Use sandbox based on policySources: codex-rs/protocol/src/protocol.rs379-426
The SandboxManager::transform() method converts a CommandSpec into an ExecEnv by wrapping the command with platform-specific sandbox wrappers.
Transform Flow:
CommandSpec Structure:
| Field | Type | Description |
|---|---|---|
program | String | Executable name or path |
args | Vec<String> | Command arguments |
cwd | PathBuf | Working directory |
env | HashMap<String, String> | Environment variables |
sandbox_permissions | SandboxPermissions | Computed writable roots and network access |
justification | Option<String> | Optional execution reason |
SandboxPermissions Structure:
| Field | Type | Description |
|---|---|---|
writable_roots | Vec<WritableRoot> | Directories that can be written, with read-only subpaths |
network_access | bool | Whether network access is allowed |
ExecEnv Structure:
| Field | Type | Description |
|---|---|---|
command | Vec<String> | Full command with sandbox wrapper (if applicable) |
cwd | PathBuf | Working directory |
env | HashMap<String, String> | Environment variables |
sandbox | SandboxType | Selected sandbox type |
windows_sandbox_level | Option<WindowsSandboxLevel> | Windows-specific sandbox level |
arg0 | Option<OsString> | Override for process name (used by Linux sandbox) |
Sources: codex-rs/protocol/src/protocol.rs379-426
Once an ExecEnv is constructed, it is passed to the execution layer (Unified Exec or Shell handler). The execution flow differs based on SandboxType:
Sources: codex-rs/protocol/src/protocol.rs379-426
The SandboxManager::denied() method attempts to detect if a command failed due to sandbox restrictions by examining exit code and stderr patterns.
Detection Heuristics:
| Platform | Detection Method |
|---|---|
| macOS Seatbelt | Exit code 1 + stderr contains "Operation not permitted" or "Sandbox" |
| Linux Landlock | Exit code 1 + stderr contains "Permission denied" or "EACCES" |
| Windows | Exit code 1 + specific error patterns from Windows API |
Denial Handling in ToolOrchestrator:
When a sandbox denial is detected:
SandboxManager::denied(sandbox_type, output) returns trueapproval_policy = AskForApproval::OnFailure:
SandboxType::None (temporary privilege escalation)This allows the agent to gracefully handle legitimate sandbox violations (e.g., writing to system directories) while maintaining security for typical operations.
Sources: codex-rs/protocol/src/protocol.rs379-426
The sandbox implementation uses environment variables for configuration and introspection:
| Variable | Value | Purpose | Set By |
|---|---|---|---|
CODEX_SANDBOX | "seatbelt" | Indicates macOS Seatbelt sandbox is active | create_seatbelt_command_args() |
CODEX_SANDBOX_NETWORK_DISABLED | "1" | Signals network access is disabled | SandboxManager::transform() (all platforms) |
CODEX_CI | "1" | Indicates execution in CI-like environment | Unified exec environment setup |
NO_COLOR | "1" | Disable color output | Unified exec environment setup |
TERM | "dumb" | Set terminal to dumb mode | Unified exec environment setup |
Unified Exec Environment:
The UNIFIED_EXEC_ENV constant in codex-rs/core/src/unified_exec/process_manager.rs defines a standard environment for PTY-based processes:
These variables ensure consistent, parseable output from commands executed in sandboxed environments.
Usage:
Processes can check these variables to detect they are running in a Codex sandbox and adapt behavior accordingly (e.g., skip network-dependent features, use alternative temp directories, disable colored output).
Sources: codex-rs/core/src/unified_exec/process_manager.rs56-67
The sandboxing implementation is validated across multiple platforms in CI/CD:
CI Validation Matrix:
Build Requirements Per Platform:
| Platform | Dependencies | Purpose |
|---|---|---|
| Linux | pkg-config, libcap-dev | Compile vendored bubblewrap |
| macOS | None (uses system Seatbelt) | N/A |
| Windows | MSVC toolchain | Compile restricted token helper |
musl Target Configuration:
For x86_64-unknown-linux-musl and aarch64-unknown-linux-musl targets, the CI installs additional build tools:
The .github/scripts/install-musl-build-tools.sh script:
RUSTC_WRAPPERSources: .github/workflows/rust-ci.yml186-510 .github/scripts/install-musl-build-tools.sh1-120 .github/workflows/rust-release.yml110-191
Codex provides CLI subcommands to test sandbox behavior interactively:
--full-auto Flag:
Applies a preconfigured "safe automatic" policy for testing:
workspace-writenever (auto-approve within sandbox constraints)--log-denials Flag (macOS only):
Captures sandbox denials via log stream and prints them after command exits, useful for debugging unexpected permission errors.
Integration Tests:
The codex-rs/core/tests/suite/unified_exec.rs test suite validates sandbox behavior:
The skip_if_sandbox!() macro conditionally skips tests when running inside a sandbox environment (detected via CI environment variables), as nested sandboxing is not supported.
Example Command Wrappers:
| Original | Transformed (WorkspaceWrite) |
|---|---|
/bin/ls /tmp | /usr/bin/sandbox-exec -p '...' /bin/ls /tmp (macOS) |
python3 script.py | bwrap --ro-bind / / --bind /workspace /workspace -- python3 script.py (Linux) |
cmd.exe /c dir | Spawned with restricted token (Windows) |
Sources: codex-rs/core/tests/suite/unified_exec.rs27-30 codex-rs/core/tests/suite/unified_exec.rs160-285
The Codex sandboxing system provides a multi-layered security architecture:
ReadOnly, WorkspaceWrite, DangerFullAccess)SandboxManager orchestrates selection and transformationThis architecture enables safe AI agent operation while maintaining flexibility for users who need reduced restrictions in trusted environments.
Refresh this wiki