The Three Approval Modes, Explained
on-request, never and a granular policy answer a question sandbox mode doesn't: not what Codex is technically allowed to do, but when it has to stop and ask you first. Until recently this page listed untrusted as the third mode. Codex no longer accepts it — and leaving it in a config can stop Codex from starting, which is the first thing worth checking if an older setup suddenly refuses to launch.
On-request: the interactive default
on-request lets commands the sandbox already permits run without asking, and prompts at the sandbox's edge: editing outside the workspace under workspace-write, or reaching the network when network access isn't enabled. Inside the boundary, reads, edits and commands just happen. That makes it the right default for supervised sessions, where you're present to answer the prompts that do appear. It's also the policy behind Codex's Auto preset.
Never: no prompting, with a standing exception
never removes prompts for everything the sandbox permits — the mode built for unattended runs such as CI, where nobody is there to answer. The exception that doesn't go away: a tool call that advertises itself as destructive still requires approval. A pipeline built on never has to plan for that case — a stalled approval with nobody present — rather than assume the run cannot be interrupted.
Granular: interactive for some prompt types, rejected for others
A granular policy, written as approval_policy = { granular = { … } } in config.toml, splits approvals by category: sandbox escalations, prompts raised by execution-policy rules, MCP elicitations, request_permissions prompts and skill-script approvals. Each category is either kept interactive or automatically rejected. It's the middle ground for a session where you want to be asked about, say, MCP calls, while anything trying to escalate out of the sandbox is simply refused rather than queued for a decision.
What happened to untrusted
untrusted used to mean "run only commands Codex already knows are safe, ask about everything else." The behavior still exists; the setting moved. To keep it for a project, remove approval_policy from your config and add a project entry to your user-level ~/.codex/config.toml: trust_level = "untrusted" under [projects."/path/to/project"]. Commands then need approval unless an execution-policy rule allows them. Two side effects are worth knowing. That entry also disables the project's own local configuration, and explicitly setting on-request overrides it. In managed environments, the allowed approval policies must include untrusted for it to apply. Search profile files, startup scripts and team-managed defaults for the old value, not just your main config.
What Codex picks on first launch
When you start Codex in a folder, it checks whether the folder is under version control. In a version-controlled folder it recommends Auto — workspace-write with on-request approvals; in one that isn't, it recommends read-only. Depending on your setup it may also start read-only until you explicitly trust the directory, through an onboarding prompt or /permissions. The workspace it protects is the current directory plus temporary directories such as /tmp, and /status lists exactly which directories count. So the approval mode most people are running was chosen by a heuristic on their first launch — worth knowing before assuming a session is configured the way you'd configure it on purpose.
The presets, read as pairs
Each named preset is a sandbox mode paired with an approval policy. Auto is workspace-write with on-request. Safe read-only browsing is read-only with on-request. The CI shape is read-only with never, so a pipeline can inspect a repository without ever stalling on a prompt. Auto-review keeps Auto's boundary but routes eligible approvals to the reviewer agent. And dangerous full access, --yolo, removes both the sandbox and the approvals; OpenAI labels it elevated risk and doesn't recommend it.
Why never isn't automatically the risky choice
It's tempting to rank never as least safe, but the ranking ignores context. In an unattended run there's nobody to answer a prompt, so a mode that keeps asking adds no safety — it produces a job that hangs. never paired with read-only is genuinely conservative. It's never paired with a permissive sandbox that deserves scrutiny, and that's a property of the pair, not of the approval mode on its own.
Approval mode and sandbox mode are independent dials
never can sit on read-only for a check that changes nothing, or on workspace-write for a pipeline expected to edit files, and those two runs carry very different risk. Reason about the two settings separately and choose the combination the task needs; the presets are just named pairs, not a third mechanism.
Auto-review: a reviewer between you and the prompt
With approvals_reviewer = "auto_review", eligible approval requests go to a reviewer agent before they reach you. It checks for data exfiltration, credential probing, persistent weakening of security and destructive actions; low- and medium-risk actions proceed where policy allows, critical-risk actions are denied, and failures fail closed. It only reviews actions that already needed approval — it never widens the sandbox. Two practical notes: the reviews are extra model calls, so they add to usage, and /approve retries one recent denial if the reviewer got it wrong.
Changing approval mode mid-session
/permissions adjusts approval and sandbox settings without restarting — start conservatively while you learn how a session behaves, loosen once it's earned it, tighten again if it drifts. Confirm what's active with /status before a long unattended stretch; discovering an hour later that a run has been waiting on a prompt is the commonest way this goes wrong.
Approval fatigue
A session that prompts constantly for low-risk, repetitive actions trains you to approve without reading — the failure prompts exist to prevent. Treat a wave of prompts as a signal: the task's scope may be wider than the sandbox boundary suits, or Auto-review or an execution-policy rule for the repeated command may fit better than clicking through.
Writing it down for a team
Agree on one approval setup for interactive work and one for CI, and record it the way you'd record a linter config — including, now, a note that untrusted is no longer a value anyone should copy from an old README.
Verified 2026-10-28 against CodexHow facts module (src/data/facts/) — see /about/#accuracy.