Codex untrusted Approval Policy Retired: What to Change

From the guide: Codex CLI Comprehensive Guide

Codex CLI v0.149.0 (stable, August 20, 2026) retired the untrusted approval policy in PR #39630, “Retire the untrusted approval policy.”1 The PR removes untrusted “from the CLI, configuration schema, and MCP tool interface,” and an explicit approval_policy = "untrusted" now fails “with an actionable error.”4 Reproduced on 0.149.1, August 25, 2026: a session launch stops with Error: approval_policy = "untrusted" is no longer supported; remove this setting whether the value sits in config.toml, a profile file, or a -c override, and the codex binary rejects -a untrusted at argument parsing.5 Change the value to on-request and leave the sandbox mode alone; for the most cautious setup, pair --sandbox read-only with on-request.3 The current policy set is on-request, never, and the granular table form.2 Current as of v0.149.1 (August 24, 2026, UTC), the npm latest.1

TL;DR

  • The change: v0.149.0’s full changelog lists PR #39630, “Retire the untrusted approval policy.” The release notes give no migration text beyond that title;1 the PR description does: untrusted is gone from the CLI, the config schema, and the MCP tool interface, and explicit settings “now fail with an actionable error.”4
  • Who must act: anyone with approval_policy = "untrusted" in ~/.codex/config.toml or a profile, and anyone passing --ask-for-approval untrusted (or -a untrusted) in scripts, aliases, or CI.
  • The replacement: on-request, with the sandbox mode unchanged. read-only plus on-request is the doc’s “Safe read-only browsing” pair.2 The old workspace-write plus untrusted combination has no direct successor; per-command prompting now lives in exec policy rules.48
  • The current set: on-request, never, or approval_policy = { granular = { ... } } for per-category control. Sandbox modes stay read-only, workspace-write, and danger-full-access.2
  • Fail-fast, not silent: a leftover approval_policy = "untrusted" stops the session with Error: approval_policy = "untrusted" is no longer supported; remove this setting, in config.toml, a profile file, or a -c override. codex doctor reports only that the config could not be loaded, without naming the key.5

What Did Codex 0.149 Change?

The headline items are new surfaces, among them the codex agents dashboard, codex queue, and a broader codex doctor; the approval change sits lower, in the full changelog.1 The description of PR #39630 carries the detail the release notes omit. Two of its three bullets matter here: “Remove untrusted from the CLI, configuration schema, and MCP tool interface. Explicit approval_policy = "untrusted" settings now fail with an actionable error.” and “Remove the known-safe command allowlist. Projects marked untrusted now request approval for every command unless an explicit exec policy rule allows it.”4 One bug fix in the same release matters for the same readers: “Resumed and forked threads now restore their active permission profile instead of silently falling back to current defaults.”1

Release item Verbatim source text Why it matters here
PR #39630 “Retire the untrusted approval policy” The value you need to remove
Thread restore fix (PR #39153) “Resumed and forked threads now restore their active permission profile instead of silently falling back to current defaults.” Old sessions carry old policy; check what a resumed thread reports
codex doctor expansion “diagnoses endpoint protection, network/proxy failures, desktop app state, and update connectivity” The first tool to run after editing config, though it does not name a retired key

Each row quotes the v0.149.0 release notes.1

Who Needs to Edit Anything?

Four places carry the value. Find all of them first, because a profile or shell alias reasserts the old policy after you fix the main file.

Location What to search for Typical owner
~/.codex/config.toml approval_policy = "untrusted" Individual developer
Profile files (~/.codex/<name>.config.toml) approval_policy = "untrusted" Anyone with more than one preset
Legacy [profiles.<name>] tables in config.toml approval_policy = "untrusted" under the table. Codex ignores the table without --profile (unless you pass --strict-config, which rejects unrecognized fields), and --profile refuses to start while one exists; move the keys to ~/.codex/<name>.config.toml and fix the value there5 Anyone who set up presets before the file-per-profile format
Scripts, aliases, Makefiles, CI --ask-for-approval untrusted, --ask-for-approval=untrusted, -a untrusted, -c approval_policy=untrusted Automation and team tooling

The legacy-table failure is loud. On 0.149.1, codex exec --profile safe "hi" with a [profiles.safe] table still in config.toml stops with Error loading config.toml: --profile `safe` cannot be used while .../config.toml contains legacy `profile = "safe"` or `[profiles.safe]` config; move those settings into .../safe.config.toml ..., so a teammate’s --profile safe fails before Codex reads the approval value.5

One grep per side:

# Config and profiles: match the key, not the bare word
grep -rnE 'approval_policy\s*=\s*"untrusted"' ~/.codex/*.toml .codex/config.toml 2>/dev/null

# Scripts, aliases, CI
grep -rn --exclude-dir=node_modules \
  -e "ask-for-approval untrusted" -e "ask-for-approval=untrusted" \
  -e "-a untrusted" -e "approval_policy=untrusted" \
  ~/.zshrc ~/.bashrc . 2>/dev/null

# CI directories: read every bare hit, because YAML can split a flag from its value
grep -rn --exclude-dir=node_modules "untrusted" .github .gitlab-ci.yml .circleci 2>/dev/null

The first grep matches the key rather than the bare word for a reason. trust_level = "untrusted" is a different setting; leave it. The configuration reference defines projects.<path>.trust_level as the key that marks “a project or worktree as trusted or untrusted,” and untrusted projects “skip project-scoped .codex/ layers, including project-local config, hooks, and rules.”7 PR #39630 changes what an untrusted project does about commands, not the key: “Projects marked untrusted now request approval for every command unless an explicit exec policy rule allows it.”4 A blind find-and-replace of untrusted corrupts that key.

Profile files are the documented preset mechanism (~/.codex/<name>.config.toml, selected with codex --profile <name>), so a teammate’s profile can reintroduce the retired value no matter what the main config says.2

What Is the Current Approval Policy Set?

Codex security comes from two layers: the sandbox mode decides what Codex can technically do, and the approval policy decides when Codex must stop and ask.2 The retirement touches only the second.

Layer Current values Notes
Approval policy on-request, never, { granular = { ... } } on-request is the interactive default in the Auto preset; never disables prompts; granular keeps chosen categories interactive and auto-rejects the rest2
Sandbox mode read-only, workspace-write, danger-full-access workspace-write keeps network off unless [sandbox_workspace_write] network_access = true2
Auto preset --sandbox workspace-write --ask-for-approval on-request Reads, edits, and runs commands in the workspace; asks before editing outside it or using the network2
Safe read-only browsing --sandbox read-only --ask-for-approval on-request Reads files and answers questions; asks before edits, commands, or network2
Non-interactive (CI) --sandbox read-only --ask-for-approval never Reads only, never prompts2

The granular form covers five prompt categories: sandbox_approval, rules (execpolicy prompts), mcp_elicitations, request_permissions, and skill_approval.2 None of them reproduces untrusted, which was a command-classification rule (auto-run known-safe reads, prompt for anything that could mutate state) rather than a prompt-category filter.2

workspace-write plus untrusted, the doc’s “Automatically edit but ask for approval to run untrusted commands” row, has no direct successor.2 workspace-write plus on-request stops prompting for commands that run inside the sandbox; read-only plus on-request prompts for edits as well as commands.2 PR #39630 removed “the known-safe command allowlist” and names the surviving mechanism for per-command prompting: “Projects marked untrusted now request approval for every command unless an explicit exec policy rule allows it.”4 Exec policy rules are the same mechanism behind the granular table’s rules category, the “execpolicy-rule prompts” the approvals page lists.2 Security owners who relied on untrusted for a writable workspace should build those rules. The rules doc scopes them to commands that run outside the sandbox; a prefix_rule with decision = "prompt" prompts “before each matching invocation”:8

# ~/.codex/rules/default.rules
prefix_rule(pattern = ["git", "push"], decision = "prompt")

The read-only sandbox remains the blunt alternative that blocks mutation outright.3

What Are the Exact Edits?

The mapping is one line: untrusted becomes on-request, and the sandbox mode stays what it was.3

Before (retired) After Where
approval_policy = "untrusted" approval_policy = "on-request" config.toml and every profile file
--ask-for-approval untrusted --ask-for-approval on-request Scripts and aliases that launch the codex TUI binary
-a untrusted -a on-request Shorthand flag, codex binary only
-c approval_policy=untrusted -c approval_policy=on-request Inline override; the form codex exec accepts
sandbox_mode = "read-only" + untrusted sandbox_mode = "read-only" + on-request The doc’s config.toml example, labeled “Always ask for approval mode”2

Main config (a profile file takes the identical edit):

# ~/.codex/config.toml (before)
approval_policy = "untrusted"
sandbox_mode    = "read-only"

# ~/.codex/config.toml (after)
approval_policy = "on-request"
sandbox_mode    = "read-only"

A script:

# before
codex --sandbox workspace-write --ask-for-approval untrusted "$@"

# after
codex --sandbox workspace-write --ask-for-approval on-request "$@"

The -a/--ask-for-approval pair belongs to the codex TUI binary. codex exec has no such flag: on 0.149.1, codex exec --ask-for-approval untrusted "hi" fails with error: unexpected argument '--ask-for-approval' found.5 For codex exec, set the policy in config or pass it inline:

# non-interactive run, policy set inline
codex exec --sandbox workspace-write -c approval_policy=never "$@"

Two judgment calls follow. First, where nobody can answer a prompt, the interactive codex binary under on-request stalls on the first approval; the documented non-interactive pair is --sandbox read-only --ask-for-approval never, and codex exec --sandbox workspace-write is the documented non-interactive entry point.2 Second, if you paired untrusted with danger-full-access for “full power, but ask every time,” that property does not survive the swap. The doc’s two examples of an on-request prompt are leaving the sandbox and using the network, and danger-full-access removes both triggers.2 Prompts from the granular table’s other four categories still fire under full access: exec policy rules with decision = "prompt", MCP elicitations, skill approvals, and request_permissions prompts.28 The optional approvals_reviewer = "auto_review" setting routes eligible prompts through a reviewer agent; it applies only to interactive policies, so it remains available after the migration.2

How Do I Verify the Change Took?

  1. Run codex doctor. With the retired value still in config, its config line begins ✗ config config could not be loaded and the detail line reads · failed to load Codex config; doctor does not name the offending key. The named error comes from launching codex or codex exec. A clean doctor line means the value is gone; a failed one means you still have to launch a session to see which key.5 The launch error is identical whether the value sits in config.toml, in a profile file selected with --profile, or in a -c approval_policy=untrusted override.5 The flag form fails earlier, at argument parsing: codex -a untrusted --version prints error: invalid value 'untrusted' for '--ask-for-approval <APPROVAL_POLICY>' followed by [possible values: on-request, never].5
  2. Start a throwaway session in a scratch directory and run /status. Its Permissions line shows the active policy, and on-request renders there as “Ask for approval”.5 /permissions opens the preset menu rather than reporting the active mode, so read /status instead.5 /status also lists the workspace directories.2
  3. Resume one older thread. PR #39153, “Restore permission profiles when resuming threads,” now restores “the latest persisted approval policy, approvals reviewer, and active permission-profile ID when resuming or forking a thread.”6 A resumed thread whose persisted policy is untrusted remains untested; treat that case as unknown until you open one.

One caveat on the documentation itself. The official “Agent approvals & security” page, as captured on August 24 and re-checked on August 25, 2026, still shows --ask-for-approval untrusted in its combinations table, still carries the prose paragraph that begins “With --ask-for-approval untrusted, Codex runs only known-safe read operations automatically,” and still uses approval_policy = "untrusted" in its config.toml example.2 The configuration reference’s approval_policy entry lists untrusted first in its type union while its description marks a different value as retired: “on-failure is deprecated; use on-request for interactive runs or never for non-interactive runs.”7 The PR and the binary are the authoritative record; the docs lag them. Do not copy the doc’s example block into a fresh 0.149 install without swapping the value.

FAQ

What replaces approval_policy = "untrusted" in Codex?

approval_policy = "on-request", with your existing sandbox_mode unchanged. For the most cautious combination, set sandbox_mode = "read-only" alongside it.3

Which Codex version retired the untrusted policy?

v0.149.0, stable on August 20, 2026, via PR #39630 in the full changelog. v0.149.1 (August 24, 2026, UTC) is the current npm latest.1

What happens if I leave untrusted in config.toml?

Codex refuses to start the session. On 0.149.1, codex exec stops with Error: approval_policy = "untrusted" is no longer supported; remove this setting, the same error appears for a profile file and for -c approval_policy=untrusted, and codex doctor reports only that the config could not be loaded.5 PR #39630 describes the behavior as failing “with an actionable error.”4

Is on-request less safe than untrusted was?

Inside workspace-write, yes: untrusted prompted before any command that could mutate state, and on-request runs in-sandbox commands without asking.2 The sandbox layer recovers part of the margin: read-only blocks writes regardless of policy, and on-request still asks before any escalation.3 For per-command prompting on a writable workspace, write exec policy rules, the mechanism PR #39630 names.48

Do I need to change my sandbox mode too?

No. The retirement affects only the approval policy; keep read-only, workspace-write, or danger-full-access as you had it.3

Key Takeaways

For individual developers: - Grep ~/.codex/*.toml for approval_policy = "untrusted" (not the bare word), replace each hit with on-request, and leave sandbox_mode and any trust_level = "untrusted" alone. - Run codex doctor, then /status in a scratch session, and resume one old thread to see what 0.149 restores.

For teams maintaining shared profiles and scripts: - Fix profile files and inline overrides in the same commit as config.toml; a legacy [profiles.<name>] table blocks --profile entirely until you move it to ~/.codex/<name>.config.toml.5 - Convert unattended jobs to --sandbox read-only --ask-for-approval never on the codex binary, or codex exec --sandbox workspace-write -c approval_policy=never; the interactive codex binary under on-request blocks on a prompt nobody will answer, and codex exec has no --ask-for-approval flag.5

For security owners: - The untrusted classifier (auto-run safe reads, prompt on mutation) has no granular equivalent; PR #39630 points at exec policy rules (“unless an explicit exec policy rule allows it”) for per-command prompting,4 written as a prefix_rule with decision = "prompt" in ~/.codex/rules/default.rules,8 and the read-only sandbox blocks mutation outright. - Consider approvals_reviewer = "auto_review" where a reviewer agent can stand in for a human on eligible prompts.

References


  1. OpenAI, Codex CLI v0.149.0 release notes, published August 20, 2026 (stable). New features quoted verbatim; PR #39630 “Retire the untrusted approval policy” appears in the release’s full changelog; the thread-restore bug fix quoted verbatim. v0.149.1 (published August 24, 2026, UTC) is the npm latest. Verified 2026-08-24. 

  2. OpenAI, “Agent approvals & security”. Sandbox and approval layers, the Auto preset, the common combinations table (including the “Safe read-only browsing” and “Automatically edit but ask for approval to run untrusted commands” rows), --ask-for-approval never, the granular approval_policy table and its “execpolicy-rule prompts” category, approvals_reviewer, profile files, /status for workspace directories, and codex exec for non-interactive runs. As captured 2026-08-24 and re-checked 2026-08-25, the page still shows untrusted in its combinations table, in the prose paragraph beginning “With --ask-for-approval untrusted,” and in its config.toml example. 

  3. Blake Crosley, Codex CLI guide, guide v2.59 (2026-08-25). Editorial migration mapping: approval_policy = "untrusted" to approval_policy = "on-request" with the sandbox mode unchanged; read-only plus on-request labeled “Maximum safety” in the guide’s sandbox-mode table. 

  4. OpenAI, PR #39630, “Retire the untrusted approval policy”, merged August 20, 2026 (UTC). Description quoted verbatim: “Remove untrusted from the CLI, configuration schema, and MCP tool interface. Explicit approval_policy = "untrusted" settings now fail with an actionable error.” and “Remove the known-safe command allowlist. Projects marked untrusted now request approval for every command unless an explicit exec policy rule allows it.” Verified 2026-08-25. 

  5. Author’s reproduction on Codex CLI 0.149.1 (npx -y @openai/[email protected] with a scratch CODEX_HOME), August 25, 2026. Covers the -a untrusted argument error; the approval_policy = "untrusted" config error from codex exec --skip-git-repo-check with the value in config.toml, in ~/.codex/safe.config.toml under --profile safe, and as -c approval_policy=untrusted; codex doctor output with that config; the codex exec --ask-for-approval rejection; the legacy [profiles.safe] error under --profile safe; and the /status Permissions label. 

  6. OpenAI, PR #39153, “Restore permission profiles when resuming threads”, merged August 18, 2026 (UTC). Description quoted verbatim: “Restore the latest persisted approval policy, approvals reviewer, and active permission-profile ID when resuming or forking a thread.” Verified 2026-08-25. 

  7. OpenAI, Codex Configuration Reference, fetched as Markdown 2026-08-25. The approval_policy entry’s type union reads untrusted | on-request | never | { granular = { ... } } (granular keys elided) and its description includes “on-failure is deprecated; use on-request for interactive runs or never for non-interactive runs.”; the projects.<path>.trust_level entry defines the trusted/untrusted project marker quoted above. 

  8. OpenAI, Rules, fetched 2026-08-25. The page opens “Rules are experimental and may change.” The decision field’s three values, quoted verbatim: “allow: Run the command outside the sandbox without prompting.” “prompt: Prompt before each matching invocation.” “forbidden: Block the request without prompting.” The user-layer file is ~/.codex/rules/default.rules, the path Codex writes to “when you add a command to the allow list in the TUI”; the page’s own example prompts before gh pr view. Codex “applies the most restrictive decision when more than one rule matches (forbidden > prompt > allow).” 

Related Posts

Install and Update Claude Code CLI: Mac, Linux, Windows

Every way to install, update, pin, and uninstall the Claude Code CLI -- native installer, Homebrew, winget, or npm -- on…

7 min read

Codex Hooks Make the Harness Real

Codex hooks, Remote SSH, and mobile control make agent work operational. Evidence, approvals, git custody, release gates…

11 min read

Foundation Models from Python: the fm CLI

macOS 27 ships the fm command line tool plus a Foundation Models SDK for Python, so you can script Apple's on-device mod…

14 min read