Codex desktop: permission state (activePermissionProfile/approvalPolicy/writableRoots) silently degrades to :workspace + sandbox_approval: false over successive read-only turns in the same task

Open 💬 2 comments Opened Aug 25, 2026 by gibney0164
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary
Within a single Codex desktop task, the effective permission state (activePermissionProfile, approvalPolicy, approvalsReviewer, writableRoots) silently degrades over successive turns — even when no files, settings, or the model are changed, and even though the on-disk config.toml defaults never change. Over three consecutive read-only status requests in one task, the state went from the correct configured profile down to bare :workspace with sandbox_approval: false and almost all writable roots removed.
This was independently confirmed by reading .codex-global-state.json directly, not just from the app's own self-reported status — the per-thread heartbeat entry in the state file matches the degraded values exactly.
Environment
Platform: Windows, Codex desktop app (please fill in exact build number from Settings → About — omitted here since it wasn't captured during the investigation)
Account: authenticated via ChatGPT; no organization-managed requirements.toml or managed_config.toml present at any documented system/user location
config.toml throughout this entire test: approval_policy = "on-request", approvals_reviewer = "user", default_permissions = "husum-property-files" — unchanged at every turn
Steps to reproduce
Start a new Codex task with a profile that has an explicit default_permissions set in config.toml (in this case, a custom profile husum-property-files).
Ask for a read-only status report of activePermissionProfile, approvalPolicy, approvalsReviewer, sandbox approval status, and writable roots.
Without making any file changes, permission changes, or model changes, ask for the identical read-only status report again.
Repeat once more.
Observed behavior (this run)
Turn 1 Turn 2 Turn 3
activePermissionProfile husum-property-files (extends :workspace) null / missing :workspace
approvalPolicy "on-request" "on-request" {"granular": {"sandbox_approval": false, "rules": false, "skill_approval": false, "request_permissions": true, "mcp_elicitations": true}}
approvalsReviewer "user" "user" "user"
writableRoots 7 entries, including the task folder, F:\Pictures\My Pictures, two OneDrive project folders, and .codex\memories same 7, plus an unrequested broader root (C:\Users\Dave Gibney\Documents\Codex, the parent of the task folder) only the task's own temp visualization directory — all 6 other roots gone, including F:\Pictures\My Pictures
Turn 3's values were independently verified against .codex-global-state.jsonelectron-persisted-atom-state.heartbeat-thread-permissions-by-id["<thread-id>"] directly on disk, and match the app's self-report exactly:

{
  "activePermissionProfile": { "id": ":workspace", "extends": null },
  "approvalPolicy": {
    "granular": {
      "sandbox_approval": false,
      "rules": false,
      "skill_approval": false,
      "request_permissions": true,
      "mcp_elicitations": true
    }
  },
  "approvalsReviewer": "user",
  "sandboxPolicy": {
    "type": "workspaceWrite",
    "writableRoots": ["C:\\Users\\<user>\\.codex\\visualizations\\2026\\08\\25\\<thread-id>"],
    "networkAccess": false,
    "excludeTmpdirEnvVar": false,
    "excludeSlashTmp": false
  }
}

Expected behavior
A task's effective permission profile, approval policy, reviewer, and writable-root allowlist should not change between turns unless the user, the config, or the model changes. Three plain read-only status requests in the same task should return identical values each time.
Additional related finding (separate but adjacent bug)
Before the above was reproduced, a different desync was found and had to be manually patched: two host-scoped keys in the same state file — electron-persisted-atom-state.agent-mode-by-host-id.local and electron-persisted-atom-state.preferred-non-full-access-agent-mode-by-host-id.local — remained stuck at "guardian-approvals" (left over from earlier "Approve for me" usage) even after permission-selection-by-host-id:local was cleared and config.toml correctly specified approvals_reviewer = "user". As long as those two keys held "guardian-approvals", new tasks' approvalsReviewer came back as auto_review regardless of config.toml. This suggests the app keeps more than one on-disk representation of "current permission mode" per host, and they can desync from each other and from config.toml. Setting agent-mode-by-host-id.local to "auto" and preferred-non-full-access-agent-mode-by-host-id.local to null (matching a known-good backup from earlier the same day) resolved that specific symptom — approvalsReviewer correctly held at "user" through all three turns of the test above, even while the separate per-turn degradation (this report's main subject) still occurred.
Impact
Permission-dependent file operations (in this case, work on personal photo files) cannot be safely performed partway through a task, since the writable-root allowlist and sandbox approval behavior cannot be trusted to hold steady even across read-only turns. The only currently-known-reliable point is the first turn of a brand-new task.

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 2 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #40392

Powered by Codex Action

gibney0164 · 2 days ago

Related: this looks like the same underlying issue as #33702 (macOS) and #23958 (Linux) — permission/reviewer/sandbox state desyncing or drifting mid-session without an explicit user action. Neither has a response either. Cross-platform (Windows/macOS/Linux) and going back to at least May suggests this is a core app-server bug, not something OS-specific