Codex Desktop create_thread does not inherit auto-approval mode for worktree tasks
What version of the Codex App are you using (From “About Codex” dialog)?
ChatGPT Desktop powered by Codex & OWL, version 26.707.71524.
Bundled Codex CLI/runtime reported by the child sessions: 0.144.2.
What subscription do you have?
Not relevant to the local permission inheritance behavior / not checked.
What platform is your computer?
Microsoft Windows NT 10.0.19045.0, AMD64.
What issue are you seeing?
Codex Desktop's official create_thread tool does not inherit the configured auto-approval mode when it creates a task in a managed worktree.
The Desktop host default is auto approval:
agent-mode-by-host-id.local = guardian-approvals
preferred-non-full-access-agent-mode-by-host-id.local = guardian-approvals
The parent task also had:
approval_policy = on-request
approvals_reviewer = auto_review
sandbox_policy = workspace-write
However, two independently created managed-worktree child tasks both started their first turn with:
approval_policy = on-request
approvals_reviewer = user
sandbox_policy = workspace-write
As a result, the children displayed manual approval dialogs for routine escalated operations that normally pass through the auto reviewer, including git fetch, git add, and GitHub CLI commands.
This is not a GitHub CLI installation or authentication issue. The commands work after manual approval, and the same host/default configuration uses auto review in the parent task.
Changing the child task to auto approval while its first turn is already running emits a later settings update, but the active turn continues using the original user reviewer snapshot. Every later escalation in that long-running turn still asks the user manually. The new setting only takes effect on a subsequent turn.
What steps can reproduce the bug?
- On Codex Desktop for Windows, select Auto approval as the default permission mode.
- Start a parent task and verify its turn context contains:
approvals_reviewer = auto_review.
- From that task, use the official
create_threadtool with:
- a saved local project;
environment: { type: "worktree" }.
- Let the child task begin its automatically started first turn.
- Inspect the child turn context.
- Observe that it contains:
approvals_reviewer = user.
- Have the child run a command that requires a normal scoped escalation, such as
git fetchorgit addin the managed worktree. - Observe a manual approval dialog instead of automatic review.
This reproduced twice in separate child tasks:
- Parent was
auto_reviewimmediately before the firstcreate_threadcall; the child started approximately one minute later asuser. - Parent was again
auto_reviewimmediately before the secondcreate_threadcall; the child started seconds later asuser.
Thread IDs, repository names, account names, and local paths are intentionally omitted.
What is the expected behavior?
A child task created through create_thread should inherit the effective approval reviewer from the Desktop host default or from its parent task.
With Auto approval selected, the child should start with:
approval_policy = on-request
approvals_reviewer = auto_review
If permission inheritance is intentionally unsupported, create_thread should expose an approval/permission parameter, or create the child in a paused state so the user can select its permission mode before the initial turn starts.
Changing a task's permission mode should also either affect subsequent tool calls in the active turn or clearly indicate that it will only apply to the next turn.
Additional information
Current workaround:
- Immediately stop the child task's first turn.
- Select Auto approval again inside the child task.
- Send a new “continue” message.
- The new turn then uses
auto_review.
A related Windows report, #32880, covers linked-worktree Git metadata writes and sandbox ACLs. This report is different: the commands here are deliberately escalated and succeed after approval; the defect is that the child task starts with approvals_reviewer=user despite both the host default and parent task being configured for auto review.
10 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Thanks for the duplicate check. This issue is distinct from #32612.
The affected worktree tasks were launched internally by an existing Codex parent task through Codex Desktop's official
create_threadtool. They were not manually created by the user in the UI, and the permission mode was not changed before their first turns started.Before each
create_threadcall:guardian-approvals/ Auto approval;approvals_reviewer=auto_review.Nevertheless, each internally spawned child task began its initial turn with
approvals_reviewer=user. That incorrect initialization is the primary bug reported here.#32612 covers changing access control while a turn is already running and having the change apply only to the next turn. That behavior appears here only as a secondary complication after the child has already started with the wrong reviewer. Even without any mid-turn setting change, the child task's initial permission state does not match either the host default or its Codex parent.
Reproduced on macOS as well.
26.715.71837 (5702)Reproduced a closely matching permission-inheritance failure on Windows with three parallel Worktree tasks.
Environment:
26.727.4816.010.0.19045.0Sanitized persisted state before applying a local config workaround:
All three Worktree tasks immediately surfaced manual approval dialogs for the same routine read-only inspection of the project and delegated worktree paths. The UI/global mode indicated Full access, so the repeated prompts were unexpected and blocked unattended parallel work.
This adds two observations:
Changing the visible permission mode while the active turns were already waiting did not remove the prompts from those turns, consistent with #32612.
Thread IDs, usernames, local paths, repository names, and project contents are intentionally omitted.
Reproduced on macOS with the host/UI set to Full access.
Environment:
Observed behavior:
sandbox_mode=danger-full-accesswith approval policynever, matching the UI setting.sandbox_mode=workspace-writewith a managed/restricted permission profile.<repo>/.git/worktrees/<managed-worktree>/index.lock<repo>/.git/worktrees/<managed-worktree>/sequencergit addandgit cherry-pickreturnedOperation not permitted, and the task surfaced manual permission prompts despite Full access being selected.Expected behavior:
.gitdirectory.Current mitigations are to reselect Full access inside each created task before continuing, start a fresh turn after changing permissions, or hand off to the Local checkout for Git integration. These reduce the symptom but make unattended multi-task orchestration unreliable.
Reproduced on macOS with the current stable Desktop build, and the trace narrows the divergence to fresh visible task request assembly.
Environment:
26.730.61639(bundle6234)0.147.0-alpha.1.2create_thread, saved Git project, managed worktreeapproval_policy=never,sandbox_policy=dangerFullAccessSanitized reproduction:
never/dangerFullAccess.approvalPolicy=on-requestsandboxPolicy=workspaceWriteuseAppServerPermissionDefault=falseAwaiting approvaltasks during already-authorized work.on-request/workspaceWriteand safely stopped before any tool call.useAppServerPermissionDefault=true; app-server then correctly resolved the configurednever/dangerFullAccess.create_threadprobe from that recovered parent was nevertheless again explicitly requested ason-request/workspaceWrite.This is five fresh visible destinations in one bounded transfer with the same restrictive request. It falsifies the narrower explanations that app-server default resolution, stale user configuration, reasoning effort, or inheritance only from the initially restricted parent caused the mismatch. An internal subagent created under the recovered parent inherited
never/danger-full-access, which is a useful control.The initial approval triggers included ordinary read-only advisory MCP identity/source-list calls, not Git writes or destructive commands. Corrective follow-up messages did not clear the server-initiated approval boundary; the operator had to click Stop. A manually created fresh task with Full access selected before send later passed a zero-tool
never/danger-full-accesspreflight.The current app-server contract already supports
turn/interrupt, scoped approval decline/cancel, and request-resolution events. The high-level Desktop task-creation surface exposed to a coordinator does not expose permission policy/inheritance, resolved policy before first turn, cross-task interruption, or approval resolution.Requested product behavior:
create_threadshould preserve the source/host permission posture or expose an explicit permission/inherit parameter;Privacy-safe full causal trace and recurrence matrix: https://github.com/briancl2/build-meta-analysis/issues/1535#issuecomment-5199243390
Claim ceiling: this establishes five matching fresh-task occurrences on one host/build plus contrasting same-thread/internal-subagent controls. It does not establish all hosts, models, or fresh tasks.
Reproduced on macOS with a narrower comparison between separate Desktop tasks and true collaboration subagents.
Environment:
0.147.0-alpha.6.5full-access``
toml
``approval_policy = "never"
sandbox_mode = "danger-full-access"
Observed:
approval_mode=neverandsandbox_policy={"type":"disabled"}.create_threadpath persisted instead as managed/restricted withapproval_mode=on-request. Their collaboration subagents then correctly inherited that wrong restricted task policy.spawn_agentpersisted as unrestricted/neverand completed a harmless read-only command without any approval record.create_threadtask, harmless process inspection (pgrep) was explicitly submitted withsandbox_permissions=require_escalated, producing an approval flow. That escalation was unnecessary for the operation, but it only became user-blocking because the new task had been initialized as managed/on-request.This isolates the defect to separate Desktop task creation, not generic subagent inheritance.
The current model-visible
create_threadschema exposes prompt, target/environment, model, reasoning, and title, but no sandbox or approval-policy override. By contrast, the documented App Serverthread/startrequest supports bothapprovalPolicyandsandbox. So there is currently no supported way for the creating agent to preserve Full Access explicitly when this Desktop path chooses the wrong default.Expected:
create_threadshould resolve the destination host's current Full Access default, orapprovalPolicyandsandboxfields.Existing tasks retaining their creation-time policy is expected; the bug is that newly created tasks start with the wrong policy despite both the host default and user config already being Full Access/no approvals. Local paths, repository names, task IDs, and prompt contents are intentionally omitted.
I reproduced the Full Access variant of this with fresh, visible Codex Desktop project/worktree tasks on Windows 11.
Environment:
26.803.10989.0danger-full-access, approval policynever, unrestricted permission profilecreate_threadinterface, using a local project worktreeObserved behavior:
workspace-writewith managed approval and a filesystem profile restricted to its worktree plus selected temporary/artifact paths.create_threadinterface exposes project, environment, model, reasoning, title, and prompt controls, but no permission-mode control.These were not internal sub-agents. They were visible, independently tracked Codex sessions created in managed worktrees.
Impact: ordinary delegated repository work cannot run autonomously under the permission posture selected for the parent/project, and instead encounters confirmation/escalation boundaries for operations that the originating task can perform without approval.
Expected behavior: a new tracked task should either inherit the effective parent/project permission selection, or task creation should expose an explicit permission-mode field. It would also be useful to know whether already-created tasks can be refreshed after a fix or must be recreated.
All repository names, task IDs, user paths, and worktree identifiers have been omitted intentionally.
Edit: I may have found a narrower trigger in my reproduction. The unrestricted parent was itself not manually created in the Codex UI; it was an automatically launched successor / agent-created tracked task. That task correctly had Full Access. The downgrade appeared in the next generation: visible tasks it created through
create_threadstarted restricted. I have not yet established that nesting depth or task provenance is causal, but this difference may explain why the same workflow appeared to work until today.macOS build 26.810.52044: exact root cause and regression-tested fix direction
I reproduced the Full access variant on macOS and traced it through the packaged Codex Desktop renderer.
Environment
26.810.52044(build6662)``
toml
``approval_policy = "never"
sandbox_mode = "danger-full-access"
approval_policy=never,sandbox_policy=dangerFullAccessObserved result
A task created through the model-facing
create_threadpath started with:This is a task-creation defect. It is not a later Git or sandbox failure. The restrictive tuple is selected before the destination task starts its first turn.
Exact packaged path
In this build, the renderer path is:
The relevant permission flow is:
Lfsreads the source task's effective permission selection. It correctly classifiesdangerFullAccess + neveras nativefull-access.zfsdecides whether that source selection can cross to the destination CWD.zfspreserves the selection only when its internalpermissionProfileIdstarts with:.permissionProfileId=null.zfstherefore returnsnull, even though the normalized source mode isfull-access.Rfsmaps the host's Full access selection toauto.autoresolves toworkspaceWrite + on-request.In pseudocode, the failing decision is equivalent to:
The last branch rejects a valid raw native selection solely because its internal profile ID is null.
The current model-facing
create_threadschema also has no explicit sandbox or approval fields. It exposes title, prompt, target, model, and thinking only, so the coordinator cannot correct the downgrade at creation time.Smallest fix
Preserve a normalized native permission mode across a different CWD when
permissionProfileIdis null. Keep the current non-escalation rules for restricted or special modes:full-accessread-only,auto, and granular modes without changing their levelcustomandguardian-approvalsacross CWDsAn alternative is to add explicit permission fields to
create_threadand safely pass them through to task creation. Preserving the already-normalized native source selection is the smaller change.Regression results
I made a copy-only patch and a standalone regression harness. The tests prove:
full-access+ null profile ID + different destination CWD remainsfull-accessdangerFullAccess + nevercustomandguardian-approvalsdo not become Full accessThe patch changes only the fixed-length
zfsdecision range. ASAR offsets, file sizes, unpack flags, and the ASAR header hash remain unchanged.I did not install the patched bundle. Modifying
app.asarinvalidates the OpenAI application signature and causes bothcodesign --verify --deep --strictand Gatekeeper assessment to fail. The safe delivery path is an OpenAI-signed and notarized application update.Requested action
Please apply the null-profile native-mode preservation fix, or add explicit permission fields to
create_thread, and add the regression matrix above.Label request: please add
macOS. The existingapp,app-server, andsandboxlabels are correct.Reproduced a related macOS failure today in a delegated Codex Desktop task.
The originating workflow had Full Access / approvals disabled, and the user explicitly authorized this exact browser action: open ten locally served design-preview URLs in separate tabs of the already-running Microsoft Edge CDP session.
The child task nonetheless entered
waitingOnApprovalduring the final verification phase. The pending work was ordinary local browser automation against127.0.0.1: confirming the preview tabs, then doing a viewport/DOM check. It did not involve a deployment, credential access, purchase, message, destructive action, or external data submission.Observed consequence: the child remained active but could not complete its terminal report. A coordinating task could verify that the ten tabs existed, but could not clear the child task’s approval boundary or reliably interrupt/cancel the pending request. Re-sending the explicit authorization as a follow-up message did not resolve the active turn.
This matches the broader cross-task permission downgrade/orphaned approval pattern: user authorization in the parent is insufficient once the child is created with a restrictive approval posture, and the current coordinator surface does not expose a way to inherit Full Access, resolve the child approval, or interrupt that exact pending tool call.
Requested regression coverage: create a delegated task from a Full Access parent, have it attach to an already-running local Edge CDP endpoint, create/navigate local preview tabs, and perform a non-destructive DOM/viewport check. The child should inherit
never/danger-full-access; if a confirmation is still required, the parent-provided explicit action scope should satisfy it, and the coordinator should be able to cancel or resolve a stuck child approval.