Codex Desktop silently rewrites autonomy settings, causing projectless .codex EPERM prompts
Summary
Codex Desktop silently rewrote the machine-wide autonomy tuple in ~/.codex/config.toml from:
approval_policy = "never"
sandbox_mode = "danger-full-access"
approvals_reviewer = "user"
to:
approval_policy = "on-request"
sandbox_mode = "workspace-write"
approvals_reviewer = "guardian_subagent"
Fresh projectless threads then inherited the restricted profile. Their generated workspace root was writable, but the reserved .codex child was explicitly read-only, so ordinary goal-artifact creation failed with Operation not permitted and agents requested escalation for basic local setup.
This is separate from #32039 (projectless root symlink validation). The projectless root was already repaired to a real local directory and task creation itself succeeded.
Environment
- Codex Desktop:
26.707.61608(build5200) - Codex CLI:
0.144.3 - macOS:
26.5.2(build25F84) - Architecture: Apple Silicon (
arm64)
Evidence
- A pre-incident config backup has
never / danger-full-access / user. - The rewritten
config.tomlhad a filesystem birth/modification time of2026-07-13 07:10:14 -0300, the exact second one affected projectless thread was created. - Other bounded config backups all retain the intended tuple.
- Two affected projectless thread
turn_contextrecords show: approval_policy: on-requestsandbox_policy.type: workspace-write- managed permission profile
- workspace root writable
- workspace
.codexread-only - The first ordinary
mkdir -p .codex/<goal>in each affected thread returnedOperation not permitted. - Direct
create_goalcalls later succeeded; the approval request was caused by the filesystem profile/path collision, not the goal API itself. - After restoring
never / danger-full-access / user, two fresh projectless canaries started withpermission_profile: disabled, created.codex/<goal>/goal.mdandplan.md, activated/completed goals, made ordinary local edits, and finished with no approval prompt. - No installed LaunchAgent or local maintenance script writes these settings. The exact writer is not represented by a session-level patch event, so attribution to a specific Desktop code path remains uncertain.
Observed sequence
- Configure
~/.codex/config.tomlwithnever / danger-full-access / user. - Use Codex Desktop to create projectless threads.
- Observe that
config.tomlhas been atomically replaced withon-request / workspace-write / guardian_subagent. - In a fresh projectless thread, attempt ordinary workspace-local state under
.codex/<name>. - Observe
EPERMand an escalation request.
The rewrite was not reproduced on every subsequent projectless creation, so this may depend on a settings migration or a one-time Desktop persistence path.
Expected behavior
Codex Desktop updates must preserve explicit user autonomy settings in ~/.codex/config.toml. Creating a projectless task must not silently replace them.
If Desktop intentionally migrates or overrides these fields, it should:
- expose the change clearly;
- preserve an explicit existing user choice;
- avoid making a projectless workspace's required local state path read-only; and
- never turn ordinary projectless goal setup into a user approval prompt.
Local mitigation
I restored the intended tuple and installed a narrow event-driven guard that backs up the config and repairs only the exact known-bad triple. This protects the local workflow but does not fix the underlying Desktop write.
2 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
I found and verified a second persistence layer that explains the recurrence after the original
config.tomlrepair.Corrected root cause
Codex Desktop does not rely only on
~/.codex/config.tomlfor new UI-created tasks. The renderer persists a separate local-host mode at:The signed Desktop bundle maps:
full-access->:danger-full-access+danger-full-access+never+userguardian-approvals->:workspace+workspace-write+on-requestThe UI new-task/projectless path serializes that renderer selection as explicit permissions in
start-conversation; those overrides take precedence over the still-correctconfig.tomlvalues.This also explains why a thread-tool canary was misleading: it bypassed the real renderer new-task path.
Real UI evidence
On the current signed unified app (
26.707.62119, build5211; bundled CLI0.144.2):019f5c94...began two turns asnever / danger-full-access / permission_profile=disabled.thread_settings_appliedevent switched the unchanged thread toon-request / workspace-write / auto_review / permission_profile=managed; visual history shows the permission chip changing from Full access to Approve for me.never / danger-full-access / user.never / danger-full-access / disabled, created.codex/<goal>/goal.mdandplan.md, calledcreate_goal, wrote and verified an ordinary file outside its generated workspace, completed the goal, and produced no approval request.The iCloud/projectless-root repair is unrelated: good and bad tasks use real sibling directories with identical filesystem/trust properties, and one thread flipped permission profiles without any cwd change.
Durable local mitigation
I now pin all three locally controlled boundaries:
config.toml:never / danger-full-access / useragent-mode-by-host-id.local = full-accessdefault_permissions = ":danger-full-access"and only:danger-full-accessinallowed_permission_profiles(with the required read-only sandbox fallback inallowed_sandbox_modes)The managed requirement is loaded through
com.openai.codex:requirements_toml_base64; a fresh bundled app-serverconfigRequirements/readreturns the intended allow-list/default, andconfig/readresolves tonever / danger-full-access / user. An event-driven LaunchAgent watches the config, renderer state, requirement source, and preference. A live counterfactual fromguardian-approvalswas automatically restored tofull-accesswith a backup and exit code 0.The requirement applies to all local threads, not only projectless ones, and the already-running Desktop/app-server process must restart before the permission menu is fully constrained. The immediate UI default and fresh projectless canary are already healthy.
Product fix requested
Please make this precedence explicit and safe:
.codexgoal setup into approval friction.