openai / openai/codex

Retiring approval_policy="untrusted" without deprecation weakens the execution-approval boundary

Open
#39,973 15 comments 41 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug CLI config sandbox
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

Codex 0.149.0 retired approval_policy = "untrusted" in #39630 and now refuses to start when an existing configuration contains it:

Error loading configuration: approval_policy = "untrusted" is no longer supported; remove this setting

Simply removing the setting is not a neutral migration. For a project configured with trust_level = "trusted", the effective default becomes on-request, which provides a materially weaker command-
execution approval boundary.

This is a breaking security-policy change shipped without a deprecation period, without an equivalent replacement, without migration guidance in the prominent release notes, and while the official
documentation still describes untrusted as valid and recommends it for this use case.

Previous security boundary

With:

default_permissions = "readonly-net"
approval_policy = "untrusted"
approvals_reviewer = "user"

[permissions.readonly-net]
extends = ":read-only"

[permissions.readonly-net.network]
enabled = true

[permissions.readonly-net.network.domains]
"*" = "allow"

[projects."/path/to/project"]
trust_level = "trusted"

the policy provided two separate controls:

  1. The permission profile constrained filesystem and network access.
  2. The untrusted approval policy required approval before executing commands outside the known-safe command set.

This meant repository scripts, build tools, dependency hooks, arbitrary executables, and commands with external execution paths could not run merely because they fit within the OS sandbox.

Boundary degradation after removal

The error tells users to remove the setting. In a trusted project, doing that selects on-request.

Under on-request, commands that fit inside the active permission profile may run without approval. approvals_reviewer = "user" does not restore the previous behavior; it only controls who reviews
actions already classified as requiring approval.

In the example above, read-only filesystem enforcement remains, but arbitrary code can potentially execute with:

  • read access granted by the permission profile;
  • unrestricted outbound network access; and
  • no approval prompt merely because the command is not known-safe.

That is a meaningful security-boundary degradation. Read-only protection prevents modification, but it does not prevent sensitive-data disclosure. Repository-controlled code or a compromised
dependency may be able to read accessible credentials or configuration and send them over the network.

Before:

Known-safe command?
├─ Yes: run within the sandbox
└─ No: require user approval

After following the instructed migration:

Can the command run within the sandbox?
├─ Yes: it may run automatically
└─ No: request additional permission or fail

These are not equivalent security postures.

Marking every project trust_level = "untrusted" is also not an equivalent migration. According to #39630, untrusted projects now request approval for every command unless an exec-policy rule allows
it. That is stricter than the retired policy, must be configured per project, and changes the meaning of project trust to compensate for the removal of a global approval policy.

No reasonable deprecation process

PR #39630 was merged on August 20, 2026 and included directly in 0.149.0.

Retiring a public security control in a single release by turning previously valid configuration into a startup failure—without first warning users, documenting a migration, or providing a
behaviorally equivalent replacement—is not a reasonable deprecation strategy.

For a security-sensitive setting, the startup error is especially problematic because its only remediation is:

remove this setting

It does not warn that removal may weaken the execution-approval boundary. It does not explain that trusted projects will fall back to on-request. It does not point to an equivalent supported
configuration because no equivalent appears to exist.

This retirement process makes no sense from either a compatibility or a security perspective. A normal process would include:

  1. A deprecation warning for at least one release.
  2. Documentation of the precise behavioral difference.
  3. An equivalent supported migration path.
  4. Automatic migration where possible.
  5. A prominent breaking-change notice before enforcement.

Missing from the prominent release notes

The change is present only as an entry deep in the generated full changelog:

  • #39630 — “Retire the untrusted approval policy”

It is absent from the curated New Features, Bug Fixes, and Documentation sections of the 0.149.0 release notes.

A change that invalidates existing configuration and alters a security boundary should be called out prominently as a breaking change, not left as one line among the generated commit list.

Official documentation still says it is valid

At the time of filing, current official documentation still treats untrusted as supported:

The documentation therefore directs users to configure a value that current Codex rejects at startup.

Reproduction

  1. Install a Codex version that supports approval_policy = "untrusted".

  2. Add this to ~/.codex/config.toml:

    approval_policy = "untrusted"
    
  3. Upgrade to Codex CLI 0.149.0.

  4. Run:

    codex resume
    
  5. Observe:

    Error loading configuration: approval_policy = "untrusted" is no longer supported; remove this setting
    

Requested resolution

Please consider:

  1. Restore untrusted temporarily and emit a deprecation warning.
  2. Provide a supported replacement that preserves its actual semantics:
    • run a limited known-safe command set automatically;
    • require user approval for other command execution;
    • keep this independent of filesystem/network sandbox restrictions.
  3. Add an explicit migration warning explaining that removing the setting selects on-request for trusted projects and weakens the approval boundary.
  4. Document the change prominently under “Breaking changes” in the 0.149.0 release.
  5. Correct all official documentation before removing support.
  6. Establish and document a deprecation policy for security-relevant configuration.

References

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing PR #39630 and commit 942af8447b1d1addc81fb3c3135293497d479a06 to understand the retirement and current configuration handling. Check the config.toml migration behavior, the 0.149.0 release notes, and both linked documentation pages. Done means the supported behavior, migration guidance, release notes, and documentation consistently preserve or clearly explain the approval boundary.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli, documentation, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.