Skip to content

Codex mobile remote access can reuse revoked enrollment and connect to the wrong Mac #23339

Open

Description

@Shijie-Hotone

Summary

Codex mobile remote access can enter a cross-host stale state with two Macs on the same ChatGPT account/workspace:

  • Mac A shows Codex mobile / remote access as connected or successfully set up.
  • The iPhone ChatGPT app shows or connects to Mac B instead.
  • Re-running mobile setup / scanning a new QR code on Mac A does not replace the stale enrollment.
  • Codex Desktop keeps reusing a revoked remote-control client and repeatedly reconnects to the wrong remote-control host.

This makes Mac A impossible to pair from the UI even though setup appears successful.

Environment

  • Codex App for macOS: 26.513.31313
  • macOS: 26.5, build 25F71
  • ChatGPT mobile: latest available from App Store as of 2026-05-19
  • Account/workspace: same ChatGPT account and workspace on both Macs and the iPhone
  • Setup: two Mac hosts, both used with Codex mobile remote access

Expected behavior

Each Mac should have an independent Codex mobile remote-control enrollment / host identity.

When setting up mobile access on Mac A:

  • Mac A should generate or use an enrollment for Mac A.
  • The iPhone should show Mac A as the connected host.
  • If a previous enrollment is revoked, Codex should discard it and force a fresh setup.
  • A stale or revoked enrollment from Mac B should not make Mac A appear connected.

Actual behavior

Mac A shows mobile access as connected / set up, but the iPhone shows the connected host as Mac B.

Mac A repeatedly tries to use a stale enrollment and wrong remote-control:<env> host. The local state had:

  • electron-remote-control-client-enrollments
  • added-remote-control-env-ids
  • selected-remote-host-id
  • remote-connection-auto-connect-by-host-id
  • remote-projects
  • codex-mobile-has-connected-device
  • electron-local-remote-control-installation-id

The remote project shown on Mac A was from Mac B.

Logs

Identifiers are redacted, but the important failure pattern is:

[remote-control-websocket] remote_control_client_refresh_start_request hasExistingEnrollment=true localEnrollmentClientId=<redacted stale client id> ...
[AppServerConnection] app_server_connection.transport_connect_failed errorMessage="Remote-control client has been revoked" hostId=remote-control:<redacted stale env id> transport=websocket
[remote-connections/window-context] connect_from_config_apply_failed errorMessage="Remote-control client has been revoked" hostId=remote-control:<redacted stale env id>

This repeats on app startup and QR setup retries.

Recovery attempts

Clearing the remote-control keys from ~/.codex/.codex-global-state.json while Codex is running is not sufficient because the running app rewrites the stale state back to disk.

Clearing both ~/.codex/.codex-global-state.json and ~/.codex/.codex-global-state.json.bak while Codex is fully stopped removes the local stale state. However, there is no obvious mobile UI to remove the incorrect/stale host from the iPhone side, and the Mac UI can still present misleading connected state before cleanup.

Why this looks like a product bug

The app treats a revoked remote-control enrollment as an existing valid local enrollment (hasExistingEnrollment=true) and keeps retrying it instead of invalidating it.

The UI also appears to conflate or reuse remote-control host state between two Macs on the same account/workspace. This produces a cross-host mismatch: Mac A reports success, while the iPhone points at Mac B.

Suggested fixes

  • When the relay returns "Remote-control client has been revoked", clear the corresponding local enrollment and remote host mapping automatically.
  • Do not display mobile access as connected if the stored enrollment is revoked.
  • Ensure electron-local-remote-control-installation-id / host identity cannot be cloned or reused across Macs without re-enrollment.
  • Add a visible "Remove this Mac / disconnect host" action in ChatGPT mobile Codex.
  • Add a "Reset Codex mobile pairing" action in Codex App Settings > Connections.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    app-serverIssues involving app server protocol or interfaces
    on May 18, 2026
  2. jshaofa-ui commented on May 18, 2026

    @jshaofa-ui

    🔧 Solution: Revoked Enrollment Reuse Prevention (Cross-Host Stale State)

    Root Cause Analysis

    Three failure points:

    1. Enrollment Identity Not Host-Bound (Primary): When two Macs share the same ChatGPT account, the enrollment system doesn't distinguish between hosts. Enrollment ID is shared at account level, not host level. Server-side enrollment registry doesn't validate host identity on connection.

    2. Revoked Client Reuse (Secondary): When enrollment is revoked, the client isn't invalidated. Desktop app doesn't check revocation status before reconnecting. No revocation notification mechanism from server to client.

    3. Setup Doesn't Replace Stale Enrollment (Tertiary): Re-running mobile setup doesn't invalidate existing enrollments. No "enrollment replacement" flow — only "new enrollment". Server accepts duplicate enrollments without conflict resolution.

    Proposed Fix

    Part 1: Host-Bound Enrollment Identity — Bind each enrollment to a unique host identifier (machine UUID + platform fingerprint). Server validates host identity on connection.

    Part 2: Revocation Status Check — Periodic revocation checking (every 5 min when connected). Pre-connect verification before each remote session.

    Part 3: QR Code Setup Replacement Flow — Explicitly revoke old enrollment before creating new one when scanning QR code. Verify new enrollment is active.

    Part 4: Server-Side Conflict Resolution — Prevent duplicate enrollments for same account. Notify conflicting hosts.

    Implementation Priority

    Priority Component Effort Impact
    P0 Host-bound enrollment 2-3 days Prevents cross-host confusion
    P0 Revocation check 1-2 days Stops using revoked clients
    P0 QR replacement flow 1 day Fixes setup not replacing
    P1 Server conflict resolution 2-3 days Prevents duplicate enrollments

    Files to Modify

    apps/codex-desktop/src/remote-control/enrollment.ts       [MODIFY] Add host binding
    apps/codex-desktop/src/remote-control/revocation-check.ts [NEW] Revocation monitoring
    apps/codex-desktop/src/remote-control/qr-setup.ts         [MODIFY] Replace flow
    server/src/api/remote-enrollments.ts                      [MODIFY] Conflict resolution
    apps/codex-desktop/src/remote-control/connection.ts       [MODIFY] Pre-connect verification
    

    Full solution document: ~/.hermes/solutions/codex-23339-revoked-enrollment-reuse-security-fix.md

  3. neilsanghrajka commented on May 25, 2026

    @neilsanghrajka

    Faced this as well, have a macbook pro and macbook air. Connected macbook air to my iphone via chatgpt app, suddenly codex on both macbook pro and macbook air started showing connected to the same device

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 appapp-serverIssues involving app server protocol or interfacesbugSomething isn't workingremote

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions