# Codex CLI Permissions & Control Model, Explained

Codex CLI's approval policies (on-failure is gone), the Guardian auto-reviewer, permission profiles, the sandbox on each OS, requirements.toml for enterprises, and where the model ends. Hooks have their own reference. Current to 0.147.

# The Codex CLI control model, explained

Codex CLI's control story used to be easy to summarize: strong sandbox, coarse approvals, no extension surface. That summary is now wrong in every clause. Through spring and summer 2026 OpenAI shipped a [full hooks system](/blog/codex-cli-hooks-reference) (on by default, Claude Code-compatible), fine-grained permission profiles, an enterprise constraints file, a native Windows sandbox, and — in 0.147 — a **reviewer agent** that approves on your behalf. This page is the current reference, and several widely-repeated facts about Codex are stale; we flag each. Current to 0.147.

*This page covers Codex CLI's own controls. For wiring ACP into Codex, see the [install guide](/integrations/codex).*

## Approvals: three policies and a Guardian

The approval policy is one of **`untrusted`** (prompt for anything not known-safe), **`on-request`** (the agent escalates when it needs more than its sandbox allows — the default pairing in the standard "Auto" preset with a workspace-write sandbox), or **`never`**. Stale-fact flag #1: **`on-failure` was removed in 0.143** — a lot of 2025-era writeups still list it. The `/approvals` slash command is likewise gone, replaced by `/permissions`.

Approval answers include a design we'd like others to copy: **`approved_with_amendment`** — approve *and* persist a prefix rule to `~/.codex/rules/default.rules`, so the approval becomes reviewable standing policy instead of invisible session memory. Enterprises can constrain what those rules may say (managed prefix rules can only `prompt` or `forbid`, never auto-allow).

**The Guardian (0.147)** is the headline: `--approve-for-me` (honest alias: `--not-so-yolo`) routes sandbox escalations, blocked-network requests, and side-effecting calls to a reviewer agent that checks for exfiltration, credential probing, persistence, and destruction. Critical findings deny outright; high-risk ones escalate to the human; **reviewer failures fail closed**. With Claude Code's auto mode and Cursor's Auto-review, that's all three major harnesses replacing the human prompt with a model in the same season — [the pattern and its gaps](/blog/claude-code-auto-mode-wrote-a-policy) apply to all three.

## The rules and profiles

Config is layered TOML: CLI flags → project `.codex/config.toml` (**trusted projects only** — untrusted projects skip all `.codex/` layers, and 0.147 requires explicit trust for unfamiliar ones) → profile file → `~/.codex/config.toml` → system → managed. Stale-fact flag #2: profiles are now separate files selected with `--profile`; `[profiles.x]` blocks inside config.toml are rejected since 0.134.

**Permission profiles (beta)** are the new fine-grained layer: named profiles with filesystem path→`read|write|deny` maps (deny beats write beats read; glob deny-reads like `"**/*.env" = "deny"`) and per-domain network allow/deny — declarative resource policy rather than command patterns.

For command patterns, the exec-policy docs deserve credit for stating the limits precisely: compound `bash -lc` scripts are only split into rule-checkable subcommands for linear `&&`/`||`/`;`/`|` chains of plain words — **redirections, command substitution, env-var assignments, wildcards, or control flow disable splitting entirely**, and the rule matches the whole blob or nothing. That's the honest version of the caveat every string-matching permission system carries.

**Enterprise**: `requirements.toml` (filesystem, MDM, or cloud-delivered from the ChatGPT workspace) sets hard constraints — which approval policies, sandbox modes, reviewers, and permission profiles are even selectable, network allowlists, and `allow_managed_hooks_only`. This is real fleet policy — for this one harness. It can carry ACP's hook to every seat: [the Codex enterprise rollout](/docs/enterprise/codex).

## The sandbox

Three modes: `read-only`, `workspace-write` (network **off** inside it by default), `danger-full-access`. Subprocesses inherit the boundary. Platform mechanics — both stale-fact flags: **Linux is now bubblewrap + seccomp with Landlock demoted to fallback**, and **Windows has a native sandbox as the default** (low-privilege sandbox users, ACLs, firewall rules; elevated and unelevated variants) rather than "use WSL." The old `codex debug seatbelt`/`landlock` subcommands are gone; `codex sandbox` runs arbitrary commands under the policy, which is a genuinely useful way to *test* what your profile allows before an agent finds out for you.

## The hooks

Stale-fact flag #3, and the biggest one: **Codex ships a native hooks system, stable and enabled by default from 0.145.0** — the earlier `codex_hooks` flag was under development and off by default, and is now a deprecated alias that warns on launch.

<div style="margin:16px 0 20px;padding:16px 20px;border:1px solid var(--line-2);border-radius:10px;background:var(--color-accent-light,#f0effe);">
  <p style="margin:0;font-size:15px;line-height:1.6;"><strong>Hooks have their own page.</strong> <code>hooks.json</code>, every event, the <code>PreToolUse</code> deny and rewrite contract, exit code 2, trust review, async hooks, and troubleshooting: <a href="/blog/codex-cli-hooks-reference" data-track="CodexControls: Hooks Reference">the Codex CLI hooks reference</a>. That page is kept current as Codex moves; this one keeps only what the hooks mean for the control model.</p>
</div>

Three things about hooks bear on the control model rather than the mechanics. The trust step: a non-managed hook does not run until a person reviews and trusts its exact definition, and the trust is recorded against the hook's hash, so an edited hook goes back to review. The fleet step: `requirements.toml` can set `allow_managed_hooks_only = true`, which skips user, project, session, and plugin hooks and runs only the managed ones — [the enterprise rollout page](/docs/enterprise/codex) has the file. And the sentence in OpenAI's docs that every hooks page should carry: treat tool hooks as "a useful guardrail, not a complete enforcement boundary."

## The record

Session rollouts as JSONL under `$CODEX_HOME/sessions/` with a local state DB, resume/fork/archive, and opt-in OTel. Deliberate anti-records exist too: `codex exec --ephemeral` skips persistence, `history.persistence = "none"`, and `codex delete` is permanent — fine for privacy, worth knowing when you're reasoning about what evidence will exist later. No independent decision ledger; the rollout is the run's own account.

## Escape hatches and the empty chair

The hatches are explicit and tiered: `--sandbox danger-full-access` (drops the boundary, keeps approvals), `--yolo` (drops both), `--approve-for-me` (keeps the sandbox, delegates approvals to the Guardian), `--dangerously-bypass-hook-trust` (one invocation's hook review). `--full-auto` was deprecated and removed from `codex exec` in 0.147.

Headless, Codex gets the empty chair right: `codex exec` defaults to a read-only sandbox and **never prompts — blocked actions fail back to the model** as errors it can adapt to. Every would-be ask resolves to deny-and-continue, which is exactly what [the empty-chair test](/blog/interactive-vs-autonomous-the-empty-chair-test) asks for. The risk profile is therefore concentrated in the flags: an unattended invocation is one `--yolo` in a cron job away from no controls at all, and nothing records that the flag was set.

## Where the native model ends

Codex's 2026 arc is the fastest control-surface improvement of any harness — from coarse approvals to profiles, Guardian, native hooks, and fleet constraints in about six months. The structural edges that remain:

- **Reviewer opacity.** The Guardian's verdicts, like every classifier gate, are judgment without a queryable rationale trail. Fail-closed is the right default; explainability isn't there yet.
- **Per-harness fleet policy.** `requirements.toml` is real enterprise control — for Codex. The same constraints don't exist for the [other harnesses](/controls) on the same laptops, and each vendor's channel carries a different file: [what the four admin channels share](/docs/enterprise).
- **The record is the run's own,** local, and deliberately deletable.
- **String rules stop at the documented line.** The exec-policy splitting rules are honest about exactly where pattern matching gives up; past that line, enforcement has to live in the sandbox, a profile, or a hook.

The composition: keep the sandbox (it's excellent), keep exec's deny-and-continue posture, and put workspace policy on the hook seam — which, now that Codex speaks the Claude Code hook contract natively, is the same seam we already stand on everywhere else. [Our integration](/integrations/codex) carries the same rules across Codex, Claude Code, and the rest, with every decision — including which escape-hatch flags a session ran under — in a ledger off the machine.

## Frequently asked questions


