/goal continuation can reuse stale permission context after Full Access/custom permissions
Summary
Codex Desktop can continue a /goal run with stale permission settings even when the visible/global configuration is Full Access with approval_policy = "never".
This appears to be a /goal-specific path: current thread/goal/set sends only goal fields, while normal turn/start and thread/settings/update carry the current permission context. If the goal RPC immediately wakes a continuation, that continuation can inherit stale live/persisted thread settings.
Observed case
- User-reported session/thread id:
019ef286-ba82-7eb0-bcad-2a85f8798cda - Platform: Windows Codex Desktop
- App version observed in local logs:
26.616.71553 - Effective user config at the time of repair:
approval_policy = "never"
sandbox_mode = "danger-full-access"
default_permissions = ":danger-full-access"
[windows]
sandbox = "elevated"
Evidence from local state/log inspection
- The affected thread/state had stale
approval_mode = 'on-request'with a managed/restricted sandbox policy despite global Full Access config. - The global heartbeat file had stale
workspaceWrite/on-requestpermission contexts for several goal-related entries. - Normalizing the persisted state back to
approval_mode = 'never'and full-access/disabled sandbox restored the expected behavior locally. - As of public
mainate476fc16ce810495cbfabe4f815d20947da0ba79,ThreadGoalSetParamsstill contains onlythread_id,objective,status, andtoken_budget. turn/startandthread/settings/updatealready carry/applyapprovalPolicy,approvalsReviewer,sandboxPolicy, andpermissions.
Root cause hypothesis
/goal uses thread/goal/set, then goal runtime effects can immediately start or resume autonomous continuation. Because thread/goal/set does not carry the current permission context, that continuation can run under stale live/persisted thread settings that predate the user's current Full Access/custom-permissions selection.
This matches the user-visible symptom: normal turns may work after permission changes, but /goal can reintroduce old approval prompts or restricted sandbox behavior.
Proposed fix direction
I prepared a local patch draft against main that does the following:
- Adds optional fields to
ThreadGoalSetParams:approval_policy,approvals_reviewer,sandbox_policy, andpermissions. - Sends the current permission context from TUI
/goalset/status calls. - Resolves named/custom permission profiles in the app server before applying goal changes.
- Adds
CodexThread::apply_thread_settings_overrides(...)and applies goal permission context beforeset_thread_goal(...).apply_runtime_effects(...)can wake continuation. - Updates generated TypeScript and JSON schema fixtures.
I could not open a PR directly from this environment because the GitHub connector reports push: false for openai/codex and no PR-creation tool is exposed. The local patch passed git diff --check; generated JSON fixtures parse with ConvertFrom-Json. I could not run cargo fmt, cargo check, or Rust tests because cargo, rustc, and rustfmt are not installed on PATH in this Windows Codex Desktop environment.
Related issues
- openai/codex#22090 describes essentially the same
/goalstale permission context failure and was closed, but current publicmainstill appears to lack permission context onThreadGoalSetParams. - openai/codex#24326 was closed as a duplicate with similar full-access goal continuation behavior.
- openai/codex#28574, openai/codex#28776, and openai/codex#28988 also look related to permission persistence/full-access prompt regressions.
Could someone on the Codex team confirm whether the intended fix is to propagate/apply permission context through thread/goal/set, or whether this should instead reuse the existing thread/settings/update path before goal runtime effects are applied?
6 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Patch draft generated locally against
main(e476fc16ce810495cbfabe4f815d20947da0ba79). Static validation only:git diff --checkpassed and edited JSON fixtures parse withConvertFrom-Json; Rust checks could not be run becausecargo/rustc/rustfmtare unavailable in this environment.<details>
<summary>Diff</summary>
</details>
I would make the goal path preserve the same invariant as a normal turn start: no continuation may wake under a permission context that is older than the user's current visible thread policy.
The dangerous ordering is not just schema drift. It is goal state update, then runtime effects, then autonomous continuation before approvalPolicy, approvalsReviewer, sandboxPolicy, and permission profile have been reconciled. I would test that at the boundary where thread/goal/set applies runtime effects.
Useful regression shape:
That keeps the product rule simple: whatever policy can authorize or block the next autonomous step must be the policy the user can inspect before that step starts.
Boundary: architecture and regression-test feedback only; no claim about using this project or running its code.
A continuation should snapshot the effective permission context at the moment it is scheduled, not reuse an earlier live context implicitly. The goal update and wake-up should be one atomic transition carrying a permission_context_version. If the visible profile changes before dispatch, the continuation should either rebind to the new context or stop with a clear mismatch, never merge fields from both. A regression can create a goal under restricted access, switch to full access, resume, and assert one coherent version across every continued turn.
I am seeing a similar stale-permission-context problem, but through subagent dispatch rather than only
/goalcontinuation.The parent agent is granted Full Access and reports that permissions were updated. However, when it dispatches a subagent, the child does not appear to receive the updated effective permission context. The child then behaves as if it is still running under a previous or more restricted sandbox/approval setting.
From the user perspective this is very hard to reason about: the main session says permissions were updated, but autonomous follow-on work can still run with stale permissions. This seems like the same underlying class of issue: continuation/delegated execution needs to receive the current effective permission context before it starts.
Fresh reproduction on 2026-07-26; this is still present in a newer Windows Desktop build.
Environment
26.721.4979.010.0.26200(build26200)neverObserved behavior
After the Goal resumed/continued autonomously, the effective turn context was managed/restricted even though the user had selected Full Access. Ordinary Unity MCP/tool calls repeatedly surfaced approval UI, making unattended Goal execution unusable.
Important details:
require_escalated.danger-full-access, approval policynever, and unrestricted/disabled filesystem permissions.Minimal reproduction shape
Expected behavior
The first and every subsequent autonomous Goal continuation should inherit the current visible Full Access policy before any tool decision is made. A Goal must not silently fall back to a managed/restricted profile.
This makes Goal mode effectively unusable for unattended work on the current Windows Desktop build, so the issue is not limited to the older version originally reported.