Browser plugin bootstrap fails in Codex App: browser-client is not trusted

Open 💬 15 comments Opened May 30, 2026 by workpodsjun
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

Browser plugin / in-app browser automation fails during bootstrap in the Codex desktop app.

Environment

  • Codex App version: 26.527.31326
  • Thread id: 019e7814-b976-73a0-aaa2-36cc02b620be
  • This thread is being used from the Codex desktop app, not only from CLI/cmux.

Error

privileged native pipe bridge is not available; browser-client is not trusted

Minimal checks

  • The in-app browser itself is visible in the Codex App UI.
  • Browser skill bootstrap uses an absolute path import for browser-client.mjs.
  • No localhost navigation, URL transition, tab creation, or real UI inspection was attempted.
  • nodeRepl exists.
  • nodeRepl.nativePipe is false / missing.
  • requestMeta keys are only progressToken, threadId, and x-codex-turn-metadata.
  • Browser backend metadata is not visible in request metadata.
  • Computer Use has worked separately in a Codex App session with list_apps.

Current diagnosis

The trusted native bridge / browser backend metadata for the Browser plugin appears not to be injected into this thread's Node REPL runtime, even though the thread is being used from the Codex desktop app and the in-app browser is visible.

View original on GitHub ↗

15 Comments

github-actions[bot] contributor · 1 month ago

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

  • #23884
  • #24845
  • #23831

Powered by Codex Action

workpodsjun · 1 month ago

Additional recovery attempt:

  • Ran codex plugin remove browser@openai-bundled.
  • Ran codex plugin add browser@openai-bundled.
  • Confirmed browser@openai-bundled is installed and enabled again.
  • In the existing Codex App thread, nodeRepl.nativePipe is still false / missing.
  • Request metadata still only has progressToken, threadId, and x-codex-turn-metadata.
  • Browser bootstrap still fails with:
privileged native pipe bridge is not available; browser-client is not trusted
  • Also tried js_reset before running bootstrap again. Same result.

Current interpretation: plugin reinstall succeeds, but the existing thread's Node REPL runtime still does not receive the Browser plugin trusted native bridge / backend metadata.

workpodsjun · 1 month ago

Follow-up after reviewing the duplicate candidates suggested by the bot.

I checked the suggested issues:

  • #23884: same browser-client is not trusted / native pipe bridge unavailable error, but reported on Windows / Chrome plugin.
  • #24845: same class of browser-client/native-pipe issue, also Windows-focused.
  • #23831: closest recovery pattern. It describes a plugin marketplace/cache/trusted-path mismatch after update, and a recovery path of fully closing Chrome and Codex, starting Codex first, waiting for bundled plugin refresh, then reopening Chrome if external Chrome control is needed.

What is similar:

  • The visible error is the same:
privileged native pipe bridge is not available; browser-client is not trusted
  • Local plugin files and browser-client cache can exist while the active runtime still does not receive a trusted browser-client/native-pipe path.
  • A thread/runtime/tool-injection mismatch remains a plausible root cause.

What is different in this report:

  • This is macOS, not Windows.
  • The primary failing surface is the Browser plugin / in-app browser automation (iab), not only the external Chrome plugin.
  • Chrome extension and native messaging host checks pass.
  • Browser/Chrome browser-client.mjs hashes match the trusted hash configured locally.
  • Loading from both the cache path and bundled marketplace path still fails.
  • A Browser plugin remove/add reinstall completed successfully, but the existing thread still had no nodeRepl.nativePipe.
  • A fresh Codex App thread with @Browser also failed at bootstrap before any tab creation, URL navigation, localhost access, or UI inspection.

Current narrowed failure point:

  • nodeRepl.nativePipe is missing.
  • browser-related env keys are not visible in the Node REPL runtime.
  • request metadata does not include browser backend metadata.
  • Therefore the Browser plugin trusted native bridge/backend metadata does not appear to be injected into the active Codex App thread runtime.

So this may be related to the duplicate candidates, especially #23831, but I do not think it is an exact duplicate unless the same fix is expected to cover macOS Browser plugin / in-app browser automation as well.

dingjianhui123-create · 1 month ago

Additional Windows recovery datapoint from another affected machine. This is not an official fix, but it may help narrow down the failure mode.

Environment:

  • Windows x64
  • Codex App 26.527.3686.0
  • codex-cli 0.135.0-alpha.1
  • bundled browser, chrome, and computer-use plugins at 26.527.31326

Symptoms observed:

  • browser-client is not trusted
  • privileged native pipe bridge is not available
  • Computer Use also failed with native pipe unavailable/path unavailable errors
  • codex plugin list --marketplace openai-bundled could show plugins as enabled, while runtime bootstrap still failed
  • after a restart, Browser/Chrome regressed to not installed because local plugin cache directories/manifests were missing

What recovered this machine:

  1. Closed Codex/Chrome where possible before cache repair, because live Node/Codex/plugin smoke-test processes can lock native files under the plugin cache.
  2. Restored missing browser, chrome, and computer-use plugin cache directories/manifests from the bundled marketplace source. Avoided overwriting already-loaded native files while Codex was running.
  3. Ensured these plugin blocks existed and stayed enabled:
[plugins."browser@openai-bundled"]
enabled = true

[plugins."chrome@openai-bundled"]
enabled = true

[plugins."computer-use@openai-bundled"]
enabled = true
  1. Added runtime env values to the local node_repl MCP server:
[mcp_servers.node_repl.env]
NODE_REPL_TRUSTED_BROWSER_CLIENT_SHA256S = "<sha256 values for the installed bundled browser/chrome/computer-use client scripts>"
SKY_CUA_NATIVE_PIPE_DIRECTORY = "\\\\.\\pipe\\codex-computer-use-<current-session-id>"

The important part was not hard-coding someone else's values. The SHA-256 list was computed from the installed plugin client files on that machine, and the Computer Use pipe was discovered from the current live \\.\pipe\codex-computer-use-* pipe.

  1. Because the Computer Use pipe changes after Codex restarts, I added a local Windows scheduled-task watchdog that runs once per minute and only writes when needed. It:
  • restores missing bundled plugin cache/manifests if absent
  • recomputes trusted client SHA-256 values from installed plugin files
  • refreshes SKY_CUA_NATIVE_PIPE_DIRECTORY to the current live pipe
  • keeps the three bundled plugins enabled
  • creates a timestamped backup before changing config.toml
  • uses a mutex to avoid concurrent writes

Verification after repair:

  • config.toml parsed successfully
  • codex mcp get node_repl showed the expected env entries
  • codex plugin list --marketplace openai-bundled showed Browser, Chrome, and Computer Use as installed, enabled
  • Browser smoke test succeeded with both Chrome and Codex In-app Browser listed
  • Chrome smoke test succeeded when using the dynamic browser id returned by agent.browsers.list()
  • Computer Use smoke test succeeded with sky.list_apps() and sky.list_windows()

My interpretation:

  • For a simple marketplace/cache mismatch, the "fully close Chrome and Codex, start Codex first, wait for plugin refresh, then reopen Chrome" recovery is safer and should be tried first.
  • In this case that was not enough, because plugin cache/manifests, trusted client hashes, and a session-specific Computer Use pipe all had to be kept in sync.
  • The ideal official fix would make this unnecessary by ensuring bundled plugin cache regeneration, trusted browser-client injection, and native-pipe discovery are handled atomically by Codex Desktop instead of relying on user-maintained config.toml repair scripts.

Sanitized write-up of the local repair is here:

https://gist.github.com/dingjianhui123-create/9c3c2b83c2a45c2ef32f9991e712edba

benjo456 · 1 month ago

Same here

Keesan12 · 1 month ago

The first thing I would separate here is trust/bootstrap failure from normal browser availability.

A useful repro matrix is just four checks in order: extension installed, extension enabled, native host present, then a lightweight tab-list/bootstrap call. If the first three are true and the bootstrap still says the browser client is not trusted, that points to the trust handshake itself rather than Chrome not being there.

The most helpful receipt is usually the first failing primitive plus the exact profile/browser context it ran under. Once you have that, this class of bug gets much easier to pin down than a generic "browser failed" report.

workpodsjun · 1 month ago

Follow-up from the same macOS/Codex App environment on 2026-06-05.

The issue is still reproducible in the current CLI-backed session.

Minimal smoke results:

  • Browser / in-app browser bootstrap still fails before any tab creation, navigation, localhost access, or UI inspection.
privileged native pipe bridge is not available; browser-client is not trusted
  • Computer Use is also currently not usable from this session: the minimal list_apps call timed out after 120 seconds.

Current interpretation:

  • The Browser plugin failure still looks like a trusted native bridge / runtime injection problem rather than ordinary browser availability.
  • The Computer Use timeout suggests the local UI automation bridge is also not healthy in this session, even though the bundled plugins are enabled in local config.

No secrets or local file contents are included here.

cypres0099 · 1 month ago

Same root cause as #21719 — full evidence posted there. tl;dr: the trust gate isn't the failure. On app build 26.611.62324 (engine 0.140.0-alpha.19, macOS arm64), browser-client.mjs hashes to exactly NODE_REPL_TRUSTED_BROWSER_CLIENT_SHA256S and sits under NODE_REPL_TRUSTED_CODE_PATHS, yet hasNativePipe: false. The reason nativePipe is missing: the desktop app-server and the Chrome extension-host each open their own /tmp/codex-browser-use/<uuid>.sock and never connect, so no privileged pipe is ever handed to node_repl. A full clean-slate restart (wiping chrome-native-hosts*.json + all sockets) does not fix it — the mismatch reproduces immediately. Detailed lsof/registry evidence in #21719.

roytong9 · 10 days ago

I am seeing the same issue on macOS arm64 after today's migration/update to the new ChatGPT desktop app.

Environment:

  • ChatGPT.app / Codex version: 26.707.31428 (build 5059)
  • Bundle identifier: com.openai.codex
  • Chrome extension version: 1.2.27203.26575_0
  • macOS arm64

Error:
privileged native pipe bridge is not available; browser-client is not trusted

What I verified:

  • ChatGPT.app settings show the Google Chrome integration as connected
  • The official ChatGPT Chrome extension is installed and enabled
  • Native messaging host manifest validation passes
  • Extension ID, host name, allowed origin, executable path, and latest symlink are correct
  • extension-host-config.json was initially missing and was regenerated using the bundled installer
  • The Chrome integration and browser extension were removed and reinstalled
  • ChatGPT.app and Chrome were restarted
  • A completely new Codex task was used for verification
  • The bridge still reports browser-client is not trusted before any tab or page data can be read

Additional context:
Earlier today, the previous Codex desktop app crashed during an update and became ChatGPT Classic.app. I then installed the new ChatGPT.app, which contains ChatGPT, Work, and Codex. The two apps have separate bundle identifiers and separate application-support directories, and ChatGPT Classic is not using the active ~/.codex configuration.

There appears to be a mismatch between the UI state and the runtime trust state:

  • Desktop UI: Chrome integration connected
  • Chrome UI: extension installed
  • Native host: valid
  • Privileged native pipe: unavailable / untrusted

The in-app feedback submission also failed with “Unable to submit your feedback. Please try again later.”

I have redacted diagnostic reports available if maintainers need them.

Cuizi7 · 8 days ago

I can reproduce the same failure on ChatGPT desktop 26.707.51957 (5175), macOS 26.5.1 arm64:

privileged native pipe bridge is not available; browser-client is not trusted

As in the original report, nodeRepl exists but nodeRepl.nativePipe is missing, and the failure occurs before any browser connection or tab operation.

I found two additional lifecycle clues:

  1. A task-level code-mode Node kernel remained alive from before the ChatGPT app was reinstalled/restarted. The affected existing task continued using that older kernel, which did not have the current privileged native-pipe bridge. Reinstalling the app alone therefore did not resolve the issue.
  1. During startup, the desktop logs show bundled-plugin reconciliation first writing a six-plugin marketplace that excludes Browser and uninstalling browser@openai-bundled. A few seconds later it writes a seven-plugin marketplace including Browser, reinstalls it, and shortly afterward installs it again with reason outdated.

The app, Browser plugin, and Chrome plugin versions all match 26.707.51957, and the installed browser-client.mjs hashes are identical, so this does not appear to be corrupted plugin files.

This suggests that stale per-task kernels and/or the bundled-plugin startup reconciliation race can leave an existing task without Browser trust registration. Full app restart, reinstall, or bundled-plugin reload should probably invalidate affected kernels and create a fresh trusted runtime.

Feedback ID: 019f5909-bc40-7fc2-9447-1690c7511f04

Cuizi7 · 7 days ago

I cloned and traced the current public openai/codex source, compared it with rust-v0.144.1, inspected the packaged ChatGPT Desktop runtime, and correlated that with the local startup logs/process lifecycle.

Source boundary

The exact failing implementation is not in the public repository. Current main (2f7d89b141) and the release-era tags have no implementation of nodeRepl.nativePipe, browser-client.mjs, or this trust error. Those pieces are supplied by the packaged Desktop node_repl/Browser bridge.

The packaged Desktop code constructs the node_repl MCP configuration from the available Browser backends and supplies NODE_REPL_TRUSTED_BROWSER_CLIENT_SHA256S. In this reproduction the packaged Browser/Chrome client hashes match, so the message browser-client is not trusted is misleading: the immediate condition is that the privileged bridge was not injected into the active kernel.

The public source does explain why reinstalling the UI may not repair that runtime state:

The public code-mode runtime is not the closed node_repl kernel itself, but it demonstrates the same persistent per-thread lifecycle boundary that Desktop needs to handle.

Proposed fix

I suggest treating every privileged Browser kernel as belonging to a versioned capability generation:

generation = hash(
  desktop_build,
  node_repl_build,
  browser_plugin_id_and_version,
  enabled_browser_backends,
  sorted_trusted_browser_client_hashes,
  bridge_protocol_version
)

On Desktop initialize/reconnect, app update, bundled-plugin install/update/remove/reload, or trust-manifest change:

  1. Compare the desired generation with each existing task kernel.
  2. If it differs, gracefully shut down and reap the old kernel; do not reconnect to it.
  3. Create a new kernel from the final MCP environment and inject nodeRepl.nativePipe before evaluating plugin code.
  4. Perform a nativePipe:v1 capability/health handshake before advertising Browser availability.
  5. If bridge injection fails, recreate once and then report a distinct native bridge missing error instead of browser-client is not trusted.

The bundled-plugin reconciliation should also be transactional. The observed startup sequence first published a six-plugin set without Browser and uninstalled browser@openai-bundled, then a few seconds later published seven plugins and reinstalled it. A provisional feature-gated plugin list should never drive destructive uninstall. Wait for authoritative feature availability, compute one final set, atomically publish it, then refresh/rebind affected runtimes.

Finally, task kernels should be owned by the app/app-server lifecycle and killed/reaped on full quit, update handoff, thread unload, or generation mismatch. A detached kernel from the previous installation was still alive in this reproduction, which explains why reinstalling the app alone had no effect.

Regression tests

  1. Delay feature availability so startup first sees 6 plugins and later 7. Assert Browser is never transiently uninstalled and only one authoritative reconcile mutates installed state.
  2. Create generation N, update/reload Browser to N+1, then resume the same task. Assert the old PID is dead, the PID changes, and nodeRepl.nativePipe.createConnection exists.
  3. Restart/update Desktop while a task kernel is alive, reconnect to the persistent non-stdio app-server, and resume the task. Assert generation mismatch forces runtime replacement.
  4. Verify the bundled client succeeds while copied/modified/non-bundled clients remain denied.
  5. Verify stale registry PID/socket cleanup and distinguish a rendezvous failure from an actual hash/path trust rejection.

I found no public PR or commit on current main that addresses nativePipe, this exact error, or #25247, so the direct patch likely belongs to the closed Desktop/node_repl owner rather than codex-rs.

Keesan12 · 4 days ago

The additional reproductions are useful because they point to a packaging/trust mismatch, not a generic browser startup failure.

It may help to make startup emit a small machine-readable boundary check before launching:

  • expected bridge artifact/hash
  • packaged artifact/hash
  • trust-policy decision
  • exact missing capability
  • terminal status such as package_mismatch, bridge_unavailable, or policy_denied

Right now several distinct failures collapse into the same user-facing retry path. Preserving that boundary result would prevent repeated bootstrap attempts and give maintainers comparable evidence across app builds.

alik-git · 3 days ago

Reproduced on a newer release after a full Mac restart:

  • ChatGPT/Codex desktop: 26.715.21425 (build 5488)
  • macOS: 26.5.2
  • In-app feedback ID: 019f7130-bf27-7913-8146-1983c831ca0a

Current diagnostics:

  • browser@openai-bundled and chrome@openai-bundled are installed and enabled
  • Google Chrome is running
  • ChatGPT Chrome Extension is installed and enabled in the selected Chrome profile
  • Native Messaging Host manifest exists and validates correctly
  • Browser and Chrome bundled clients are identical

Despite this, Browser/Chrome bootstrap still fails immediately with:

privileged native pipe bridge is not available; browser-client is not trusted

The failure occurs before opening or inspecting any tab. Restarting the Mac and ChatGPT did not restore the trusted native bridge.

This confirms the issue persists in desktop build 26.715.21425 and is not limited to the older builds reported above. The in-app feedback submission above contains the corresponding desktop diagnostic context.

alik-git · 3 days ago

Follow-up: I found a working macOS-only local workaround for this failure. I am sharing the architecture rather than the implementation so other affected users and maintainers have a concrete path forward.

Basic workaround

  1. Leave ChatGPT Desktop running so it owns the Browser/Chrome rendezvous sockets.
  2. Launch the code-signed Node runtime bundled inside ChatGPT.app as a separate, on-demand helper outside the affected task worker's sandbox. A normal system Node process was rejected by the socket/sandbox boundary.
  3. In that helper, provide the missing nodeRepl.nativePipe.createConnection interface using a normal Unix-domain socket connection adapter, together with the minimal configuration and task metadata expected by the bundled client.
  4. Load ChatGPT's existing bundled browser-client.mjs unchanged from the app bundle.
  5. Use the client's official agent.browsers API. Keep its security/elicitation policy active: deny external origins by default and exact-allow-list only the origin needed for the current task.
  6. Stop the helper after the browser task. No daemon, LaunchAgent, login item, app modification, signature patch, plugin replacement, or persistent configuration change is required.

Why this works

The failing task runtime has the official Browser client but never receives nodeRepl.nativePipe. ChatGPT's own signed Node executable passes the app's native peer authorization and can reach the existing Browser rendezvous socket. The helper therefore supplies only the missing connection adapter in an authorized signed process while continuing to use OpenAI's bundled client, protocol, APIs, and origin policy.

Validation

On ChatGPT Desktop 26.715.21425:

  • both Codex In-app Browser and Chrome were discovered through the official client;
  • In-app Browser created a tab, navigated to an explicitly allowed origin, read title/URL/DOM, used locators, and captured a screenshot;
  • Chrome created and inspected a tab, then finalized and closed it;
  • all helper processes and test tabs were stopped afterward.

A fresh task still reproduces privileged native pipe bridge is not available; browser-client is not trusted through the normal built-in path, so this is a workaround, not a repair.

Important limits

  • Only tested on macOS and this app build.
  • Internal app paths or bridge details may change after an update.
  • Do not run ChatGPT as root, patch app signatures, use a copied/modified client, bypass origin policy, or leave a persistent privileged helper running.
  • The proper fix remains for Desktop to inject/rebind the trusted native-pipe capability into the task runtime automatically.

Related in-app feedback

  • Follow-up feedback containing these workaround diagnostics: 019f71ba-c90e-73b0-b8c7-83caa1c7f5b9
GiGiBoom666 · 2 days ago

Additional macOS reproduction with read-only local diagnostics.

Environment

  • ChatGPT / Codex Desktop: 26.715.31925
  • macOS: 26.5.2 (arm64)
  • Thread: 019f74c8-162e-7800-a94d-7554c9fb7a09
  • App session: a1344c11-7b80-498d-9a5d-f1bf91c96f93
  • Browser plugin: browser@openai-bundled version 26.715.31925
  • Reinstalling ChatGPT Desktop and restarting did not resolve the issue.

Failure

The bundled Browser bootstrap fails immediately, before any tab inspection or navigation:

privileged native pipe bridge is not available; browser-client is not trusted

Direct runtime checks:

typeof nodeRepl.nativePipe?.createConnection === "function"  => false
requestMeta keys => progressToken, threadId, x-codex-turn-metadata

There is no x-codex-browser-use-available-backends metadata on the actual Node REPL request.

What is healthy

  • The Browser plugin is installed and enabled.
  • App, Browser, and Chrome plugin versions match.
  • The installed Browser and Chrome browser-client.mjs files are identical.
  • Their SHA-256 is:

461c4ba94b821ec805da79c8e8138fe510b1b3358609fc93da47387a2cf3fbf3

  • That hash is present in NODE_REPL_TRUSTED_BROWSER_CLIENT_SHA256S.
  • The running node_repl MCP server process received the expected Browser-related environment keys, including BROWSER_USE_AVAILABLE_BACKENDS, NODE_REPL_TRUSTED_BROWSER_CLIENT_SHA256S, and NODE_REPL_TRUSTED_CODE_PATHS.
  • Desktop successfully created a per-thread Browser Unix socket and logged the IAB backend as ready.

However, lsof showed only ChatGPT listening on the per-thread socket; the task's node_repl process never connected. The Desktop log likewise contains listener-start events but no peer connection/authorization event for this thread.

Startup reconciliation race observed

On this launch, Desktop performed the following sequence:

10:30:48Z  wrote bundled marketplace with 6 plugins (Browser absent)
10:30:49Z  uninstalled browser@openai-bundled as not_in_bundled_marketplace_plugin_names
10:30:52Z  wrote bundled marketplace with 7 plugins (Browser present)
10:30:53Z  installed Browser with reason=missing
10:30:55Z  installed Browser again with reason=outdated
10:30:57Z  reconciliation completed

The current task's Node REPL process was created several minutes after the final reconciliation, so this specific reproduction is not only an old pre-reconciliation kernel. The final failure point is the capability handoff: Desktop has a live per-thread socket and the trusted client configuration, but the active task kernel is not given nodeRepl.nativePipe or the Browser backend request metadata.

This appears to confirm both the bundled-plugin reconciliation race and a separate Desktop/app-server → per-thread Node REPL native-pipe injection/rebinding failure.