cheat sheet
Approvals & Sandboxing
Control what Codex CLI can do — approval policies (untrusted, on-request, never), sandbox modes (read-only, workspace-write, danger-full-access), OS-native sandbox mechanics, and --full-auto.
Approvals & Sandboxing
What it is
Codex CLI has a two-axis safety model: approval policy (when to ask you before executing a command) and sandbox mode (what the OS lets the agent do even if it tries). They compose independently — you can run full-auto with OS-level write isolation, or require explicit approval for every command in an unsandboxed session.
Approval policies
An approval policy is a session-wide rule that tells Codex when to pause and ask a human before running a command. It is enforced before the command is dispatched to the OS, sitting in front of the sandbox layer. The four built-in policies — untrusted, on-request, on-failure, never — trade off speed against safety; on-request is the sweet spot for most interactive work. Set globally in config.toml or per-run with -a / --ask-for-approval.
| Policy | When Codex asks for approval | Typical use |
|---|---|---|
untrusted | Every mutating command (writes, deletes, network calls) | Reviewing unfamiliar code |
on-request | Only when sandbox escalation is needed | Default for interactive sessions |
on-failure | After a command fails | Deprecated — avoid |
never | Never — agent runs fully autonomously | Default for codex exec / CI |
Set globally
# ~/.codex/config.toml
approval_policy = "on-request"
Output: (none — config file)
Override per run
codex --ask-for-approval untrusted
codex -a never
Output: (TUI opens with specified approval policy)
Approve or deny at runtime
When Codex requires approval, it pauses and shows the proposed command. Respond with:
- y / Enter — allow this command
- n — deny (agent sees a rejection signal and adjusts)
- a — allow all remaining commands this session
- e — edit the command before running
- w — allow this command and all matching commands in this session (e.g., approve
pytestonce and Codex stops asking forpytest …for the rest of the session)
Example interactive approval prompt:
Agent wants to run: rm -rf node_modules/
Approve? [y/n/a/e/w]
Pre-approve commands via config (no prompt, even under on-request):
[[auto_approve]]
matcher = "^(pytest|ruff|mypy)( |$)"
Output: (none — config file)
Sandbox modes
The sandbox is the OS-level enforcement layer — what the agent can do even when no approval is required. It composes independently with the approval policy: you can run read-only + on-request (read-only sandbox plus a prompt before any net-touching command), workspace-write + never (writes inside cwd only, no prompts), or any other pairing. The three modes — read-only, workspace-write, danger-full-access — map directly to OS sandbox primitives on macOS (Seatbelt) and Linux (bubblewrap + seccomp). Set globally in config.toml or per-run with -s / --sandbox.
| Mode | Filesystem | Network | Use case |
|---|---|---|---|
read-only | No writes anywhere | Blocked | Code review, read-only analysis |
workspace-write | Writes allowed only inside cwd | Blocked by default | Normal development (safe default) |
danger-full-access | Unrestricted | Unrestricted | Trusted containers, CI with pre-reviewed code |
Set globally
sandbox_mode = "workspace-write"
Output: (none — config file)
Override per run
codex --sandbox read-only "Summarise this codebase"
codex -s danger-full-access
Output: (TUI opens with specified sandbox)
Expanding the workspace-write boundary
workspace-write defaults to cwd; you can add read-only or read-write extension directories to the sandbox:
[sandbox]
mode = "workspace-write"
extra_read_dirs = ["/usr/lib", "/opt/homebrew/share"]
extra_write_dirs = ["/home/alice/scratch"]
allow_network = false
Output: (none — config file)
Per-run additions via flag:
codex -s workspace-write --add-write-dir /tmp/build "Build the artefact in /tmp/build"
Output: (TUI opens; /tmp/build is part of the writable sandbox)
Allowing network in workspace-write
Most projects don't need it, but npm install, pip install, and docker pull do. Toggle with:
[sandbox]
mode = "workspace-write"
allow_network = true
Or per-run:
codex -s workspace-write --allow-network "Run npm install and report what failed"
Output: (TUI opens with network egress permitted)
--full-auto shorthand
--full-auto is the most common single flag in real Codex usage: a single token that means "give the agent a safe-default sandbox and only prompt me if it needs to escalate." It is functionally equivalent to --sandbox workspace-write --ask-for-approval on-request, but it is also documented as the recommended starting point for autonomous tasks. Combines workspace-write sandbox with on-request approval policy. The most common "hands-free" setup:
codex --full-auto
codex --full-auto "Add unit tests for all public functions"
Output: (TUI opens; agent runs autonomously, prompts only for sandbox escalation)
In config.toml you can achieve the same default:
approval_policy = "on-request"
sandbox_mode = "workspace-write"
Output: (none — config file)
Platform sandbox mechanics
The sandbox is enforced by the host OS, not by Codex itself. Codex's job is to describe the policy ("writes restricted to cwd, no network") and ask the kernel to enforce it. The mechanism differs per platform but the rules are the same. Read this section if you need to debug a sandbox denial or understand exactly what the agent can and cannot do.
macOS — Apple Seatbelt
Codex uses sandbox-exec with a Seatbelt policy. The policy:
- Allows reads everywhere
- Restricts writes to the working directory subtree
- Blocks outgoing network by default (
workspace-write) - Escalates to full access under
danger-full-access
Sandbox violation log (visible when --debug is passed):
codex --debug "Write to /etc/hosts"
Output:
[sandbox] denied: write /etc/hosts — outside workspace
Print the active Seatbelt policy:
codex sandbox print-policy
Output:
(version 1)
(deny default)
(allow file-read*)
(allow file-write* (subpath "/home/alice/myproject"))
(deny network*)
Linux — bwrap + seccomp
Codex uses bubblewrap to create a user namespace with:
- Bind-mount of the working directory (read-write)
- Read-only bind-mounts for system paths
seccompfilter to block dangerous syscalls
Requires bwrap to be installed (usually available in distribution packages as bubblewrap).
Verify bwrap is available:
bwrap --version
Output:
0.8.0
Inspect the generated bwrap arguments (debug-only):
CODEX_LOG_LEVEL=debug codex --sandbox workspace-write "echo hi" 2>&1 | rg bwrap
Output:
[debug] bwrap --unshare-all --share-net=false --bind /home/alice/work /home/alice/work --ro-bind /usr /usr --proc /proc --dev /dev --seccomp 3 …
Windows
Two modes depending on privilege:
- Elevated — runs with current token; sandbox is permission-prompt-only
- Unelevated — restricted process token limits write scope
WSL2 environments inherit Linux (bwrap+seccomp) semantics when running inside WSL.
Docker / disposable containers
When danger-full-access is the only practical option (e.g., system-level testing), the recommended pattern is to run Codex itself inside a disposable container so that the worst-case blast radius is the container, not the host.
docker run --rm -it \
-v "$PWD":/workspace -w /workspace \
-e OPENAI_API_KEY \
ghcr.io/openai/codex:latest \
codex --sandbox danger-full-access --ask-for-approval never "Run the full build pipeline"
Output:
[agent runs unsandboxed inside the container; host filesystem is unaffected]
Per-command escalation
With approval_policy = "on-request", Codex automatically detects when an action would require sandbox escalation (e.g., writing outside cwd) and pauses to ask:
Agent wants to write to /etc/profile.d/codex.sh
This requires elevated sandbox permissions.
Allow? [y/n/a/e]
When the user denies an escalation, Codex receives a structured rejection in the agent loop and typically replans the next step. The agent does not see why the user denied — only that the operation was refused.
Practical examples
Read-only code review
codex --sandbox read-only --ask-for-approval never \
"Find all potential SQL injection vectors in this codebase"
Output: (agent analyses and reports; no writes permitted)
Safe refactor with auto-approvals
codex --full-auto "Rename all snake_case variables to camelCase in src/"
Output: (agent edits files in cwd; prompts only if it tries to go outside)
Strict interactive review
codex -s workspace-write -a untrusted "Update dependencies"
Output: (TUI opens; Codex asks before every write/delete)
CI pipeline (no approvals, confined)
codex exec --sandbox workspace-write --ask-for-approval never \
"Run the test suite and fix any type errors"
Output:
[agent output; edits committed within workspace]
Summary matrix
| Config | Sandbox | Approval | Recommended for |
|---|---|---|---|
| Default interactive | workspace-write | on-request | Day-to-day coding |
--full-auto | workspace-write | on-request | Longer autonomous tasks |
--sandbox read-only -a never | read-only | never | Analysis, summaries, reviews |
-s danger-full-access -a never | unrestricted | never | Trusted CI containers only |
-s workspace-write -a untrusted | workspace-write | always | Learning / reviewing unfamiliar repos |
Sandbox violation log
When a sandboxed agent attempts a denied operation, Codex prints a clear violation line and the agent receives a structured error in its tool result. Enable verbose logging to see every denial.
CODEX_LOG_LEVEL=debug codex --sandbox workspace-write "Write to /etc/hosts"
Output:
[sandbox] denied: write /etc/hosts (outside workspace, mode=workspace-write)
[agent] Tool call failed: PermissionDenied. Trying a different approach.
Persist sandbox violations to a log file:
[sandbox]
log_violations_to = "~/.codex/logs/sandbox.log"
tail -F ~/.codex/logs/sandbox.log
Output:
2026-05-25T14:02:01Z denied write=/etc/hosts mode=workspace-write turn=t_01abc
2026-05-25T14:03:11Z denied connect=8.8.8.8:443 mode=workspace-write turn=t_01abc
Common pitfalls
-
workspace-writeblocks network — and most builds need it.npm install,pip install,cargo build,go mod downloadall need outbound HTTPS. Either setallow_network = truein[sandbox], run those steps yourself before invoking Codex, or usedanger-full-accessinside a container. -
The sandbox only sees the current process's syscalls. Spawning a long-running daemon (e.g.,
python -m http.server &) puts the daemon outside Codex's sandbox once Codex's session exits. Usebg+disowncarefully. -
--full-autois workspace-write + on-request, not "never ask." Many people assume--full-automeans "never prompt me." It doesn't — it still asks for sandbox escalation. Use-a neverif you want truly silent automation. -
macOS Seatbelt can deny
mkdirinside cwd due to ACLs. Some directories (e.g., iCloud-synced folders) carry inherited Apple ACLs that the sandbox sees as out-of-policy. Move the project out of iCloud-Sync or setextra_write_dirs. -
WSL2 inherits Linux sandbox semantics, not Windows. If you're running Codex inside a WSL2 distro, you need
bubblewrapinstalled inside WSL — the Windows-side mechanism does not apply. -
danger-full-accessdoes NOT disable approvals. It only widens the sandbox. The approval policy still governs whether commands run. If you want no prompts AND no sandbox, use-s danger-full-access -a never(and only inside a disposable container). -
on-failureis deprecated. It existed early on as a "let the agent try, ask only if it fails" mode but produced confusing UX. Useon-requestinstead — it has the same low-friction feel without the surprise. -
A pre-approved matcher applies to the entire command, not arguments.
^pytestmatchespytest -x src/test_foo.pyANDpytest && rm -rf /. Anchor your matchers carefully — favour^pytest( |$)over^pytest.
Real-world recipes
Quick read-only review of a fork
Clone someone else's PR locally and review it without giving Codex permission to write anything.
gh pr checkout 123
codex --sandbox read-only --ask-for-approval never \
"Review this PR for correctness and security. List concerns as bullets."
Output:
- src/auth.py:42 — token compared with `==` instead of `secrets.compare_digest`
- src/db.py:17 — SQL query interpolated; vulnerable to injection
- tests/test_auth.py:88 — test depends on global state
Autonomous fix loop with safety net
Run the agent in full-auto but auto-revert if any test fails afterwards.
git stash || true
codex exec --full-auto "Fix all ruff and mypy errors in src/" && \
(pytest -x || git checkout -- .)
Output:
[agent fixes 12 ruff issues + 3 mypy errors]
142 tests passed.
Inspect what was denied during a session
After a session, look at the sandbox log for denied operations — useful for tightening or widening the sandbox.
grep "$(date +%F)" ~/.codex/logs/sandbox.log | sort -u
Output:
2026-05-25T14:02:01Z denied write=/etc/hosts mode=workspace-write turn=t_01abc
2026-05-25T14:11:55Z denied connect=registry.npmjs.org:443 mode=workspace-write
CI sandbox preflight check
Verify bwrap is installed in the CI image before invoking Codex, so failures are loud and early.
which bwrap || { echo "bubblewrap missing; install with: apt-get install bubblewrap" >&2; exit 1; }
codex exec --full-auto -p ci "Run the test suite and fix any failures."
Output:
/usr/bin/bwrap
[agent output]
Per-tool approval matcher for git operations
Auto-approve safe git inspection commands but prompt for mutating ones.
[[auto_approve]]
matcher = "^git (status|log|diff|show|blame|branch( --list)?$)"
[[deny_approve]]
matcher = "^git (push|reset --hard|clean -f)"
Output: (none — config file)