Repository navigation
Codex mobile remote access can reuse revoked enrollment and connect to the wrong Mac #23339
Description
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-enrollmentsadded-remote-control-env-idsselected-remote-host-idremote-connection-auto-connect-by-host-idremote-projectscodex-mobile-has-connected-deviceelectron-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
github-actions commentedon May 18, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
jshaofa-ui commentedon May 18, 2026
🔧 Solution: Revoked Enrollment Reuse Prevention (Cross-Host Stale State)
Root Cause Analysis
Three failure points:
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.
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.
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
Files to Modify
Full solution document:
~/.hermes/solutions/codex-23339-revoked-enrollment-reuse-security-fix.mdneilsanghrajka commentedon May 25, 2026
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