Codex Desktop switches between Ask for approval and a named profile, mismatching reviewer and sandbox
Summary
Codex Desktop can silently switch the composer permission selection between Ask for approval and a named permission profile. The selected UI label, live approval reviewer, and effective filesystem policy can disagree.
Two fresh local tasks reproduced opposite unsafe states:
- Ask for approval produced
approvals_reviewer="user", but a path explicitly denied by the named profile remained readable. - When the user submitted a correction, the composer visibly switched from Ask for approval to the named profile without the user changing it.
- A task enforcing the named profile's filesystem deny reported
approvals_reviewer="auto_review", even though both tracked and live config requestedapprovals_reviewer = "user".
This prevents the documented combination of a least-privilege sandbox boundary and user-reviewed approvals.
Environment
- Codex Desktop:
26.707.91948(build5440) - Codex CLI/runtime:
0.144.5 - macOS:
26.5.1(25F80) - Reproduced: July 16, 2026
- The behavior has occurred across fresh and resumed Desktop tasks.
Sanitized configuration
Both tracked config and live ~/.codex/config.toml contain:
approval_policy = "on-request"
approvals_reviewer = "user"
default_permissions = "custom-multi-root-profile"
The named profile grants parent traversal but explicitly denies task-history state:
[permissions."custom-multi-root-profile".filesystem]
"/Users/example/.codex" = "read"
"/Users/example/.codex/session_index.jsonl" = "deny"
"/Users/example/.codex/session_index.jsonl.*" = "deny"
"/Users/example/.codex/history.jsonl" = "deny"
"/Users/example/.codex/sessions" = "deny"
"/Users/example/.codex/sessions/**" = "deny"
Reproduction
Case A: Ask uses the user reviewer but does not enforce the named deny
- Start a new local Codex Desktop task.
- Select Ask for approval beneath the composer.
- Submit a prompt.
- Confirm the live task context reports:
``text``
approval_policy="on-request"
approvals_reviewer="user"
- Attempt a real file open against the representative denied path:
``sh``
/usr/bin/python3 -c 'import sys; f=open(sys.argv[1], "rb"); f.close()' /Users/example/.codex/session_index.jsonl
- Observed:
``text``
Exit code: 0
Output: <empty>
The file opens successfully, so the named-profile deny is not active.
- Submit a correction in the same task.
- Observe the permissions selector change from Ask for approval to the named profile during submission, without the user changing it.
- The effective runtime policy still does not reliably match the newly displayed profile label.
Case B: The named profile enforces the deny but routes approvals to automatic review
- Use a task whose effective filesystem policy contains the named deny.
- Run the same Python file-open command.
- Observe
PermissionError: [Errno 1] Operation not permitted, confirming the named deny is active. - Inspect the live task context.
- Observed:
``text``
approval_policy="on-request"
approvals_reviewer="auto_review"
- Compare with tracked and live config, which both request:
``toml``
approvals_reviewer = "user"
Additional policy checks
A focused read-only audit reported:
tracked_config: approval_policy='on-request'; approvals_reviewer='user'
live_config: approval_policy='on-request'; approvals_reviewer='user'
project_config: absent
/etc/codex/requirements.toml: absent
live_task_context: approvals_reviewer='auto_review'
Visible cloud requirements contained no allowed_approvals_reviewers or other visible rule forcing auto_review.
Expected behavior
Codex documentation describes two controls that work together:
- The sandbox controls accessible files and network resources.
- Approval routing determines whether the user or automatic reviewer handles an escalation.
- Changing who reviews a request should not expand the sandbox.
Therefore:
- A named filesystem/network profile should coexist with
approvals_reviewer = "user". - The selected permission setting should remain stable unless the user changes it.
- The UI label, live task context, and effective sandbox should identify the same active policy.
- If settings cannot be reconciled, the product should fail closed rather than silently broadening reads or changing the reviewer.
Actual behavior and impact
- Ask for approval restores the user reviewer but does not enforce the required named-profile denies.
- The named profile can enforce the denies but may route approvals to automatic review.
- The selected mode can change during message submission.
- The UI label can disagree with the effective filesystem policy.
- Restarting, starting fresh tasks, and reselecting the mode have not produced a durable repair.
This is a security and reliability problem: one state broadens access to local task-history artifacts, while the other changes who reviews escalations.
Related issues
- #22553: Desktop shows a custom profile selection but does not apply its effective permissions.
- #23875: Desktop loses
approvals_reviewerstate after context reconstruction. - #23958: A session's permission profile changes without an explicit permission command.
This report is distinct because it has a deterministic Desktop UI transition plus a two-task comparison demonstrating both sides of the mismatch: user reviewer without the named deny, and named deny with the wrong reviewer.
Requested repair
- Preserve the selected permission profile and
approvalsReviewerindependently across task start, resume, and turn submission. - Prevent message submission from changing the composer permission selection without explicit user action.
- Make the UI label, task context, and effective sandbox agree.
- Expose a supported effective-settings diagnostic showing the active permission profile, approval policy, approvals reviewer, and configuration layer or task override.
- Fail closed if task settings cannot be reconciled.
Private task identifiers and screenshots are available to OpenAI maintainers through a non-public channel if needed.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗