cool-solution — dev.blog
Technologies

Codex CLI approval policy: untrusted, on-request, never and the granular policy

The question I get most often about Codex CLI is some variant of "so when exactly does it ask for permission?". The whole answer lives in one setting, approval_policy, which too many people confuse with the sandbox: the sandbox decides what commands can technically touch, the approval policy decides when the agent must stop and wait for my yes. They are two independent dials, and configuring one while believing you fixed the other is the classic mistake. In this article I take apart the three policy values — untrusted, on-request, never — plus the two advanced options that came later: the granular policy for request categories and Auto-review, which delegates approvals to an automatic reviewer. All of it manageable mid-session with the /permissions command, no restart needed.

$ claude "refactor user.service to async/await" reading src/services/user.service.ts... proposing 12 edits across 3 files ✓ tests still pass (47 / 47) applying patch...AI PAIRsupervised

🔍 What the approval policy is and why it is not the sandbox

Codex has two separate, complementary controls. The sandbox (sandbox_mode: read-only, workspace-write, danger-full-access) is the technical boundary enforced by the operating system: where commands can write, whether they can reach the network. The approval policy (approval_policy) is the interruption protocol: in which cases Codex must stop and ask me before executing — for instance to leave the boundary, use the network, or run a command outside the trusted set.

The distinction matters because the two dials fail in different ways: a tight sandbox limits damage even with few approvals, while frequent confirmation prompts do not make an unbounded environment safe. I always configure them together, never just one of the two.

Mid-session I check them without touching any file: /status shows the active policy and sandbox, /permissions lets me switch permission levels on the fly — it is the command that early versions called /approvals. From the command line, the policy is passed with --ask-for-approval (or -a), the sandbox with --sandbox (or -s).

The two dials, in config.toml and from the CLI
# ~/.codex/config.toml
approval_policy = "on-request"   # untrusted | on-request | never
sandbox_mode    = "workspace-write"

# same thing, for a single run
codex --sandbox workspace-write --ask-for-approval on-request

# mid-session: /status to inspect, /permissions to switch

Official docs: Agent approvals & security

The default Auto preset equals workspace-write with on-request approvals.

🧭 The three values: untrusted, on-request, never

untrusted is the most conservative and the most misunderstood: Codex autonomously runs only the read operations known to be safe, and asks for confirmation on anything that can mutate state or trigger external execution paths — including destructive Git operations or flags that override configuration. I use it on repositories I do not know, where I want to see every move.

on-request is the interactive standard, the one behind the Auto preset: the agent works freely inside the sandbox and only pings me when it wants to go further — editing files outside the workspace, accessing the network, running certain commands. It is the right trade-off for daily work on trusted projects.

never disables approval prompts, but it is not the free-for-all it sounds like: the sandbox stays fully active and Codex does its best within the constraints I set. -a never with -s read-only is a read-only CI run that never stalls; with -s workspace-write it is automation confined to the repo. A note for readers of older guides: the on-failure value is deprecated — do not copy it from old examples.

There is one case where approval fires regardless of the policy I picked: calls to MCP or app tools that declare themselves destructive. If the tool advertises the destructive annotation, Codex asks for confirmation even if the same tool also claims to be read-only.

The path of a command inside Codex
  1. 01
    The model proposes an actionShell command, file edit, MCP tool call: everything goes through the same gate.
  2. 02
    The policy decides whether to stopuntrusted: confirm almost everything; on-request: only to leave the boundary; never: no prompts.
  3. 03
    Who answers the requestBy default me (approvals_reviewer = user); with auto_review an automatic reviewer answers.
  4. 04
    The sandbox executes and filtersWhatever the policy, the technical boundary remains: writes and network per sandbox_mode.

Source: official OpenAI Codex documentation — Agent approvals & security.

⚙️ Granular policy and Auto-review: the options guides skip

When "ask for everything" and "ask for nothing" are both too blunt, there is the granular policy: instead of a string, approval_policy accepts an object that governs each request category separately — sandbox escalations, execpolicy rule prompts, MCP server requests, request_permissions and skill scripts. I can keep sandbox escalations interactive and auto-reject skill scripts, for example.

The other newcomer is Auto-review: with approvals_reviewer = "auto_review", eligible approval requests no longer reach me but an automatic reviewer, which evaluates them for data exfiltration, credential access and destructive operations — denying critical-risk actions and holding high-risk ones. It only applies when approvals are interactive (on-request or a granular policy): with never there is nothing to review.

Two warnings from someone who has tried it: the reviewer evaluates only the actions that already require approval — whatever stays inside the sandbox never reaches it — and each evaluation is an extra model call, so it adds to usage. I treat it as defense in depth, not as a substitute for a tight sandbox.

Manual approvals versus Auto-review

approvals_reviewer = user

  • Every eligible request reaches me
  • Total control, but it interrupts the flow
  • Fits unknown repos and delicate tasks
  • Zero extra model cost

approvals_reviewer = auto_review

  • An automatic reviewer evaluates requests
  • Denies critical risk, holds high risk
  • Useful on long tasks I don't want to babysit
  • Extra model calls: added usage

✅ Where the settings live and the checklist I follow

Settings are layered, and knowing the precedence saves half-hour debugging sessions: CLI flags and -c overrides win, then project .codex/config.toml files (closest first), then the selected profile, then the user configuration in ~/.codex/config.toml, finally the defaults. A security detail I appreciate: project configuration is ignored until the project is trusted, so a freshly cloned repo cannot silently load its own rules and hooks.

For different contexts I use profiles: a cautious one with untrusted + read-only for exploration, a standard one with on-request + workspace-write for daily work, a never one for automation. I invoke them with --profile, and when something looks off my first command is /status, the second codex doctor.

  • Unknown repo: untrusted + read-only — I see every move, the agent writes nothing.
  • Daily work: the Auto preset (on-request + workspace-write), no flags to remember.
  • Automation and CI: never with the tightest sandbox the task allows.
  • Long unattended tasks: on-request + approvals_reviewer = "auto_review" as a middle ground.
  • Always verify: /status for the active configuration, /permissions to change it mid-session.

Frequently asked questions about codex approval policy

What is the difference between approval policy and sandbox in Codex CLI?

They are two independent controls: the sandbox (sandbox_mode) is the technical boundary enforced by the operating system — where commands can write, whether they see the network — while the approval policy (approval_policy) sets when Codex must stop and ask for confirmation. They must be configured together: a strict policy does not compensate for a wide-open sandbox, and vice versa.

What does Codex run on its own with --ask-for-approval untrusted?

Only the read operations known to be safe. Anything that can mutate state or trigger external execution paths — including destructive Git operations or configuration-overriding flags — requires my explicit confirmation. It is the policy I use on repositories I do not know yet.

With approval_policy = never is the sandbox disabled?

No: never only turns off approval prompts; the technical boundary stays fully active. With -s read-only the agent just reads; with -s workspace-write it writes only inside the repo. Removing the sandbox too requires explicit, dangerous flags like --dangerously-bypass-approvals-and-sandbox, which on my laptop never gets typed.

What is the approvals Auto-review?

With approvals_reviewer = "auto_review", eligible approval requests are evaluated by an automatic reviewer instead of me: it looks for data exfiltration, credential access and destructive operations, denying critical-risk actions. It only works with interactive approvals and uses additional model calls, so it adds to usage.

Let's talk

If this topic is relevant to you, write to me: comparing notes on code and AI is always time well spent.

All articles

More articles from the blog

hybrid-search-dotnet-qdrant-ollama.mdJuly 31, 2026claude-code-github-actions-pr-review-2026.mdJuly 30, 2026semantic-caching-llm-dotnet-redis.mdJuly 27, 2026