Skip to content

macOS Codex Desktop 26.707.91948 still overrides custom profile with never/user #33552

Open

Description

@liby

What version of the Codex App are you using (From “About Codex” dialog)?

Codex Desktop 26.707.91948 (build 5440)

Bundled Codex CLI: 0.144.5

What subscription do you have?

Not included in this public report.

What platform is your computer?

Darwin 25.5.0 arm64 arm
macOS 26.5.2 (25F84)

What issue are you seeing?

After fully quitting and restarting Codex Desktop, a completely fresh conversation still overrides the separately configured approval policy and approval reviewer when using a named custom permission profile.

The configuration contains:

approval_policy = "on-request"
approvals_reviewer = "auto_review"
default_permissions = "<named custom profile>"

The first turn of the fresh Desktop conversation recorded:

originator = Codex Desktop
source = vscode
cli_version = 0.144.5
approval_policy = never
approvals_reviewer = user
permission_profile.type = managed
sandbox_policy.type = workspace-write

The managed permission profile itself was applied, including its configured additional writable roots. However, the independent approval settings were changed from on-request/auto_review to never/user.

The bundled codex doctor --json loads the same configuration successfully:

config.load.status = ok
config.load.summary = config loaded
sandbox.helpers.approval policy = OnRequest
filesystem sandbox = restricted
network sandbox = enabled

Because the fresh thread runs with approval_policy = never, escalation requests are unavailable and auto-review cannot run.

What steps can reproduce the bug?

  1. Configure approval_policy = "on-request", approvals_reviewer = "auto_review", and a valid named custom default_permissions profile.
  2. Fully quit Codex Desktop with Cmd-Q.
  3. Reopen Codex Desktop 26.707.91948.
  4. Create a completely new conversation.
  5. Ask the first turn to report the task-injected runtime values for approval_policy, approvals_reviewer, permission_profile.type, and sandbox_policy.type without reading config.toml.
  6. Inspect the first turn context.

The new conversation receives never/user/managed/workspace-write instead of the configured on-request/auto_review approval settings.

What is the expected behavior?

A named permission profile should control filesystem and network permissions without replacing the independently configured approval policy and reviewer.

The fresh thread should start with:

approval_policy = on-request
approvals_reviewer = auto_review
permission_profile.type = managed
sandbox_policy.type = workspace-write

Additional information

This is the macOS Codex Desktop counterpart to #33084. That issue was closed after the reporter confirmed the VS Code case appeared fixed in 26.707.91948, but the Desktop reproduction above still occurs on that exact version after a full restart.

Related broader Desktop report: #32338.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    configIssues involving config.toml, config keys, config merging, or config updates
    sandboxIssues related to permissions or sandboxing
    on Jul 16, 2026
  2. github-actions commented on Jul 16, 2026

    @github-actions
    Contributor

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

    Powered by Codex Action

  3. liby commented on Aug 3, 2026

    @liby
    Author

    Still reproducible in Codex Desktop 26.803.81509 (6415, bundled CLI 0.147.0-alpha.6.6). The evidence now covers three distinct paths that can converge on a task running with never/user instead of the configured approval settings.

    1. Fresh conversation, no profile switch — observed runtime reproduction

    This is the path reported in the original issue. After fully restarting Desktop, I create a new user conversation and do not select Full Access or change profiles before the first turn.

    • Effective config remains approval_policy = "on-request", approvals_reviewer = "auto_review", with the named custom permission profile. /doctor also reports OnRequest.
    • The first turn instead reports approval policy: never, approval reviewer: user, and managed workspace-write permissions.
    • A Computer Use call to Preview is then denied because the task cannot surface an approval request. Resetting the JavaScript runtime does not change the task policy.
    • A separately created projectless task starts with an interactive approval policy and the same Preview action succeeds.
    • I did not observe a mode/profile transition that would explain the fresh task being initialized with never/user.

    This case does not require a prior Full Access selection.

    2. Full Access -> named profile — request-builder trace

    Separately, in Desktop 26.727.51351 (6119), I traced a request-construction path that can produce the same bad combination after a profile change:

    • The builder first derives { permissions, approvalPolicy, approvalsReviewer } from agentMode.
    • Full Access maps to :danger-full-access/never/user.
    • Applying a named profile then replaces only the permission profile id, leaving the stale never/user values in the request.
    • As a result, thread/start or turn/start can send <named-profile>/never/user.

    This is a separate path from the fresh-conversation reproduction above; it explains a Full Access -> named-profile transition, not why a brand-new conversation with no transition starts incorrectly.

    3. Existing conversation reset gap — request/protocol trace

    There is also a distinct reset problem for an existing conversation:

    • On a fresh thread/start, omitted approval fields can fall back to effective config.
    • On an existing thread, omitted or null approval fields are no-ops, so switching away from Full Access can retain the thread's previous never/user values.

    This likely needs an explicit reset-to-effective-config operation; omitting the fields or sending null cannot restore the configured values on an existing thread.

    Expected behavior

    • A fresh conversation must initialize its permission profile, approval policy, and reviewer from the resolved effective config, even when no settings transition occurred.
    • Full Access must remain :danger-full-access/never/user.
    • Selecting a named profile must apply the profile together with its resolved approval policy and reviewer atomically.
    • An existing conversation must have an explicit way to reset those fields to effective config.

    These paths share the same visible failure mode, but they should not be treated as one reproduction: case 1 is the current no-switch runtime reproduction, while cases 2 and 3 are the separately traced transition/reset paths.

  4. tejones36 commented on Sep 5, 2026

    @tejones36

    Still reproducible on macOS in Desktop 26.901.41123: fresh named-profile task starts with never; dropdown also disagrees with active settings

    Adding a current-version reproduction and a more specific saved-state/request-builder trace to this existing issue.

    Environment

    • ChatGPT/Codex Desktop: 26.901.41123, build 7942 (installed macOS application metadata).
    • Bundled app-server: 0.153.3, as reported in the desktop log.
    • Subscription: ChatGPT Pro.
    • macOS 26.6.2 (25G83); uname -mprs: Darwin 25.6.0 arm64 arm.
    • Observed September 5, 2026.

    Observed sequence and reproduction conditions

    1. The user-level ~/.codex/config.toml contains:

      default_permissions = "daily-work"
      approval_policy = "on-request"
      approvals_reviewer = "user"
      
      [permissions.daily-work]
      extends = ":workspace"

      The named profile additionally permits three cache directories and enables network access. Those filesystem/network details are omitted here for brevity. The full local profile was applied to the initial task.

    2. The system /etc/codex/requirements.toml contains only:

      allowed_approvals_reviewers = ["user"]

      There is no system restriction requiring approval_policy = "never", and no ~/.codex/requirements.toml exists.

    3. A new task was created with daily-work. Full access was never selected in this task. Inspection nevertheless found these existing host-level values inside electron-persisted-atom-state in ~/.codex/.codex-global-state.json:

      {
        "agent-mode-by-host-id": { "local": "full-access" },
        "permission-selection-by-host-id:local": {
          "kind": "agent-mode",
          "agentMode": "full-access"
        }
      }

      The origin of those persisted values was not established. They are a reproduction precondition found during diagnosis, not evidence of a Full access selection in the affected task.

    4. The first turn explicitly requested the following, despite the configured on-request policy. These are selected fields from the actual desktop log at 2026-09-05T20:18:46.576Z:

      requestApprovalPolicy=never
      requestApprovalsReviewer=user
      requestPermissionProfile=daily-work
      useAppServerPermissionDefault=false
      

      Subsequent turn-start records retained resolvedApprovalPolicy=never.

    5. An authorized attempt to contact another task using mcp__codex_app__send_message_to_thread failed with:

      MCP tool call requires approval, but approval policy is never
      

      No message was sent and no approval could be presented.

    6. The user then selected Ask for approval in the permission dropdown. The user reported that the visible label immediately snapped back to daily-work.

    7. The backend did change: a successful thread/settings/update was logged at 20:32:20.402Z. The following turn at 20:37:19.498Z resolved:

      resolvedApprovalPolicy=on-request
      resolvedApprovalsReviewer=user
      

      The corresponding persisted turn context showed :workspace, network access false, and none of daily-work's extra cache write roots. Saved host mode/selection became auto.

    The dropdown symptom was reported by the user; the backend settings above were independently checked in local logs and the persisted turn record. This establishes that the change took effect in the backend even though the displayed label reportedly reverted. Reapplying daily-work afterward has not been tested.

    Installed-code trace and isolated reproduction

    Read-only inspection of the installed app.asar, member webview/assets/app-initial-236e1501144c.js, found this path:

    • iro retrieves the saved host agent mode, and rro preserves an explicit full-access value.
    • Mg("full-access", ...) calls Jbt(), which supplies approvalPolicy: "never".
    • The new-task constructor Cno builds the settings from that mode, then overwrites activePermissionProfile with the named profile without replacing approvalPolicy.
    • Fjt serializes both fields into the request.

    An isolated harness using the extracted installed Mg, Jbt, Ag, Rbt, and Fjt functions, plus the profile-override assignments from Cno, produced:

    {"savedMode":"full-access","configuredApproval":"on-request","result":{"approvalPolicy":"never","permissions":"daily-work"}}
    {"savedMode":"auto","configuredApproval":"on-request","result":{"approvalPolicy":"on-request","permissions":"daily-work"}}

    This reproduces the request-building combination without changing the live app. It is consistent with the observed first-turn request and gives a concrete way that host-level saved mode can affect a brand-new named-profile task. It is not an upstream source patch or a complete end-to-end UI reproduction.

    Expected behavior

    • A fresh task created with the named default profile and configured on-request/user should use those settings, without silently inheriting never from an unrelated saved host mode.
    • The permission label should reflect the active settings. After selecting Ask for approval and the backend switching to :workspace/on-request/user, it should not still display daily-work.
    • Approval-required operations should be able to present an approval under the configured on-request policy.

    The dropdown aspect appears related to #29586 and #32338; this report adds a macOS/current-build case with a verified transition from daily-work/never to :workspace/on-request.

    Only sanitized diagnostic excerpts are included. No full logs, conversation contents, private task identifiers, or personal filesystem paths are attached. Investigation did not modify configuration or the application bundle.

  5. liby commented on Sep 24, 2026

    @liby
    Author

    Still reproducible on macOS in Codex Desktop 26.917.62051 (build 10789, bundled CLI 0.155.0-alpha.16.3). This build also shows where the approval settings are overridden.

    I had been pinning the approval settings with a requirements file delivered through the user-domain com.openai.codex / requirements_toml_base64 preference. Since #46032, that preference is honored only when forced, so the pin stopped applying and the underlying behavior became visible again.

    Fresh task with no mode or profile switch

    With approval_policy = "on-request", approvals_reviewer = "auto_review", and a named custom profile as default_permissions, I fully quit Desktop, reopened it, and started a new task on the default profile. The first turn-start log entry contained:

    requestApprovalPolicy=on-request
    requestApprovalsReviewer=user
    requestPermissionProfile=<named-profile>
    useAppServerPermissionDefault=false
    resolvedApprovalsReviewer=user
    

    The persisted turn context recorded approvals_reviewer = user. The saved host selection at the time was {"kind":"agent-mode","agentMode":"auto"}.

    Installed-bundle trace

    In the installed bundle (webview/assets/app-shared-70a4f71efb70.js and app-initial-37097744327a.js; the minified names below are specific to this build):

    • The new-task request builder derives the approval settings from the saved agent mode with zL(agentMode, runtimeWorkspaceRoots, config), then replaces only activePermissionProfile with the named default profile.
    • zL("auto") returns LL(runtimeWorkspaceRoots), whose reviewer parameter defaults to "user". zL("full-access") returns ZMe(), which is never / user.
    • Only the custom branch reads approvals_reviewer from the config, through $Me(config).

    A fresh task on a named profile therefore gets on-request / user when the saved mode is auto, and never / user when it is full-access, whatever config.toml says. That would also explain the fresh-conversation never / user case in my earlier comment if the saved mode was full-access then, although I did not capture the saved mode at the time.

    Control

    After installing the same requirements as /etc/codex/requirements.toml (allowed_approvals_reviewers = ["auto_review"]), the same steps produced requestApprovalsReviewer=auto_review in the log and approvals_reviewer = auto_review in the turn context.

    Expected: a new task on a named profile should take approval_policy and approvals_reviewer from the effective config, or omit them so the app server resolves them, instead of inheriting them from the saved agent mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingconfigIssues involving config.toml, config keys, config merging, or config updatessandboxIssues related to permissions or sandboxing

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions