Codex Desktop resumes thread with workspace-write sandbox despite UI showing Full Access

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

Summary

Codex Desktop can show Full Access in the UI while a resumed thread is actually persisted and executed as workspace-write / on-request. After stopping and restarting the same thread several times, the thread kept asking for access even though the UI still indicated Full Access.

Expected behavior

When the UI/global state says Full Access, resumed turns for that thread should start with something equivalent to:

approval_policy=never
sandbox_policy={"type":"danger-full-access"}
permission_profile={"type":"disabled"}

Actual behavior

The thread initially had many turns with:

approval_policy=never
sandbox_policy=danger-full-access
permission_profile=disabled

After a stop/restart/resume sequence, a later turn_context switched to:

approval_policy=on-request
sandbox_policy=workspace-write
network_access=false
permission_profile=managed

The local per-thread row in ~/.codex/state_5.sqlite also showed the restricted state:

approval_mode=on-request
sandbox_policy={"type":"workspace-write","writable_roots":["~/.codex/memories"],"network_access":false,...}

Meanwhile the global app state still showed Full Access, for example:

electron-persisted-atom-state.agent-mode-by-host-id.local = full-access

So the UI/global Full Access state and the persisted per-thread sandbox/approval state diverged.

Impact

The affected thread repeatedly prompts for access and cannot operate as Full Access, even though the UI says it should. Toggling the UI setting is confusing because the visible state already appears correct.

Suspected cause

The thread resume / active-goal continuation path appears to apply or preserve a per-thread workspace-write / on-request override that is not reflected by the visible Full Access UI state.

Workaround

The local workaround was to stop the running turn, fully quit Codex, back up ~/.codex/state_5.sqlite, and rewrite the affected thread row to:

UPDATE threads
SET approval_mode='never',
    sandbox_policy='{"type":"danger-full-access"}',
    updated_at=strftime('%s','now'),
    updated_at_ms=CAST(strftime('%s','now') AS INTEGER) * 1000
WHERE id='<thread-id>';

Then reopen Codex and verify the next turn_context starts with approval_policy=never and sandbox_policy=danger-full-access.

Requested fix

Please make the UI Full Access state and persisted per-thread sandbox/approval state consistent across stop/restart/resume flows, especially for active-goal continuations. If per-thread permission overrides are intended, the UI should expose and repair them instead of showing Full Access while the thread runs under workspace-write / on-request.

View original on GitHub ↗

9 Comments

github-actions[bot] contributor · 2 months ago

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

  • #24270

Powered by Codex Action

libralm · 2 months ago

Adding another report that this still appears to reproduce on a newer Codex Desktop build and is not macOS-specific.

Observed behavior from the reporter:

  • Full access is enabled.
  • If a goal/thread is started and Codex Desktop stays open for the whole run, approvals do not keep appearing.
  • If the goal is still incomplete, Codex Desktop is closed, then reopened and the same goal/thread is continued, Codex starts asking for approvals again.
  • The reporter sees the same pattern on both Windows and macOS.

Current macOS environment where this was reported:

  • Codex Desktop: 26.609.41114
  • macOS: 27.0 (26A5353q)
  • codex --version: codex-cli 0.128.0
  • Windows details are not available from this machine, but the reporter explicitly says the same restart/resume behavior happens on Windows too.

This matches the suspected resume/session state issue here: the active thread/goal seems to retain or re-enter an approval-requiring execution state after app restart/resume, even though the user believes Full Access is enabled. The key distinguishing signal is that it does not happen when the app remains open from goal start through completion; it appears after closing Codex during an unfinished goal and later continuing it.

rpelevin · 2 months ago

This looks like an effective-policy drift bug, not just an annoying approval prompt.

The user is making a decision from one surface:

  • the app says Full Access is active

but execution is governed by another surface:

  • the resumed thread still carries workspace-write / on-request state

I would make the resumed turn contract explicit: before the next model turn starts, Codex should resolve one effective execution policy and show that same policy everywhere the user is asked to reason about access.

If a saved per-thread policy wins over the global Full Access setting, that is fine as a product decision, but it should be visible as the active thread policy. If Full Access wins, the persisted per-thread row should be repaired or ignored before execution starts.

The regression I would pin is:

  1. start a thread under Full Access;
  2. stop mid-goal;
  3. fully quit the desktop app;
  4. reopen and continue the same thread;
  5. assert the first resumed turn's approval policy, sandbox policy, permission profile, network flag, and writable roots match the visible UI state.

The failure state should not be "UI says Full Access, turn context says workspace-write." That leaves the user debugging a policy they cannot see and makes permission prompts look random.

The useful invariant is simple: one resumed turn, one effective policy record, and every renderer reads from it before showing the run as ready.

BlindsidedGames · 2 months ago

Adding another concrete Windows reproduction with local evidence.

Environment:

  • Codex Desktop originator: Codex Desktop
  • CLI version recorded in session: 0.140.0-alpha.2
  • OS/shell: Windows / PowerShell
  • Workspace: C:\Users\mattr\Documents\Repositories\Space Survivors
  • Thread/session id: 019ec937-b8df-73c2-9530-325e712be3f5
  • Rollout file: C:\Users\mattr\.codex\sessions\2026\06\15\rollout-2026-06-15T12-58-53-019ec937-b8df-73c2-9530-325e712be3f5.jsonl

User-visible state:

  • Codex Desktop permissions UI showed Full access selected.
  • C:\Users\mattr\.codex\config.toml contains:
  • approval_policy = never
  • sandbox_mode = danger-full-access
  • [windows] sandbox = elevated
  • C:\Users\mattr\.codex\.codex-global-state.json contains agent-mode:full-access.
  • The same global state records this thread id as approvalPolicy:never and sandboxPolicy:{type:dangerFullAccess}.

Actual first turn context injected into the model contradicted all of that:

  • Developer permissions block said sandbox_mode was workspace-write and network was restricted.
  • The first turn_context for the same session had:
  • approval_policy:on-request
  • sandbox_policy:{type:workspace-write,network_access:false,...}
  • permission_profile:{type:managed,file_system:{type:restricted,...}}

Impact:

  • The assistant attempted to inspect an installed Steam game folder outside the workspace: C:\Program Files (x86)\Steam\steamapps\common\Soulstone Survivors.
  • Because the injected per-turn context said workspace-write/on-request, the assistant used sandbox_permissions:require_escalated, which caused an approval popup even though the UI and config were Full Access/never.
  • After the user interrupted and resumed, the newly injected environment context corrected itself to danger-full-access and approval policy: never.

This appears to be the same effective-policy drift described above: persisted UI/config/global thread state says Full Access, but the first turn in the thread can still receive a workspace-write/on-request execution contract.

YuunqiLiu · 1 month ago

I can reproduce the same effective-state drift on a long-running Linux remote/workspace session.

Sanitized observation:

  • The user-level config still specified approval_policy = "never" and sandbox_mode = "danger-full-access".
  • The project-level config contained no approval/sandbox override.
  • During the already-running root thread, injected turn_context / world_state changed the effective context to approval_policy=on-request, sandbox=workspace-write, and permission_profile=managed.
  • This occurred on 2026-07-27 around 23:17 and 23:36 Asia/Shanghai, without a user configuration or repository permission change.
  • At the restricted point, the actual work path that had previously been writable was mounted read-only and the runtime group set differed; after a later context refresh it was writable again.
  • The practical symptom was repeated approval/escalation requests for normal continuing task commands.

This looks consistent with a per-thread runtime/profile override being rehydrated independently of the user-level Full Access setting. A visible event that identifies the policy source and a way to restore the selected effective profile without restarting the thread would make this diagnosable.

I am intentionally not attaching the full rollout JSONL because it contains local paths and task content; I can provide a minimally redacted context diff if maintainers request it.

Johnny-dot · 28 days ago

Additional reproducible variant on Windows involving an existing child task resumed through send_message_to_thread.

Environment:

  • Codex Desktop on Windows
  • affected child thread: 019fb118-fc41-7001-84ca-b2536ce1723b
  • child session CLI metadata: 0.146.0-alpha.3.1

Trace:

  1. The child task originally ran with:
  • approval_policy=never
  • sandbox_policy=danger-full-access
  • permission_profile=disabled
  1. The parent task was also running with Full Access when it resumed the existing child task.
  1. At 2026-07-31T06:10:48Z, the parent called send_message_to_thread for the child.
  1. At 2026-07-31T06:10:52.081Z, the child received a host-generated thread_settings_applied event setting:
  • approval_policy=on-request
  • permission_profile=managed
  • restricted filesystem
  1. At 2026-07-31T06:10:58Z, the resumed child turn ran with:
  • sandbox_policy=workspace-write
  • approval_policy=on-request
  • permission_profile=managed

No user permission-setting action occurred between these events. The UI continued to display Full Access.

This caused repeated approval prompts for read-only commands. One in-worktree read was unnecessarily marked require_escalated by the agent, but a later outside-worktree read required approval specifically because the host had already downgraded the effective profile.

This appears to isolate the existing-task background resume/send_message_to_thread path as another trigger for the UI/runtime permission-state divergence.

SolusKossi · 9 days ago

I hit what appears to be the same UI/per-task-state mismatch on Windows Codex Desktop [26.814.41407].
This task started in “Ask for approvals.” During the task I changed the UI to “Full access,” and the banner explicitly said it could run commands with network access without approval. However, the active task continued asking for terminal approval.
After the task completed and I returned to it, the UI had reverted to “Ask for approvals” and prompted me to choose Auto-approve or keep the default. This suggests the active task retained its original on-request permission snapshot, or Full Access was only displayed in the UI and never persisted to the task.

whatthecodemean · 7 days ago

Configuration-layer finding (Windows Desktop; not a separate resume-path reproduction)

Environment

  • Codex Desktop: 26.814.5517.0
  • Bundled CLI recorded by a fresh task: 0.148.0-alpha.15

Visible configuration

  • The settings view showed Full Access for the sandbox.
  • Its approval policy was still On request.
  • Repeated approval prompts followed. That is consistent with the displayed approval setting.

Local audit

  • User-level config initially had:
  • sandbox_mode = "danger-full-access"
  • approval_policy = "on-request"
  • One trusted project also had a one-line .codex/config.toml override:
  • approval_policy = "on-request"

Result after repair

  • The project override was removed at the user's direction.
  • The user-level policy was changed to never.
  • A fresh task now records:
  • approval_policy=never
  • sandbox_policy=danger-full-access
  • permission_profile=disabled

Relevance to this issue

This report does not independently reproduce the resume regression: the observed prompts were explainable by user- and project-level configuration. It shows why the task should expose the source of its effective policy. A user needs to see whether on-request comes from user config, trusted-project config, or persisted task state; otherwise a genuine UI/runtime mismatch and an intentional configuration choice look the same.

sined-rahkuk · 5 days ago

Related but distinct reproduction: #40125. This issue covers permission drift when resuming an existing thread; #40125 captures a new create_thread worktree child starting its very first turn as on-request/managed even though the parent, host selection, and all config layers were verified never + Full Access. The child-creation API exposes no permission override.