Codex Desktop Browser Use ignores persisted origin/upload approvals when nodeRepl.config is unavailable

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

Summary

Codex Desktop Browser Use can repeatedly ask for the same origin or upload permission even after the user chooses the persistent allow option, and even when ~/.codex/browser/config.toml already says approvals should not be requested.

I reproduced this on macOS with Codex Desktop 26.519.31651 (CFBundleVersion 3017), Browser bundled plugin 26.519.22136, and Chrome bundled plugin 0.1.7.

Repro

  1. Configure Browser Use approvals to avoid repeated prompts:
upload_approval_mode = "never_ask"
history_approval_mode = "never_ask"
approval_mode = "never_ask"

[uploads]
allowed = [ "https://chatgpt.com" ]

[origins]
allowed = [ "https://chatgpt.com" ]
  1. Start a local page, for example:
python3.12 -m http.server 8767 --bind 127.0.0.1
  1. Use Browser Use to navigate to http://127.0.0.1:8767/index.html.
  2. In the approval popup, choose the persistent allow option (Always allow / 始终允许访问此网站).
  3. Navigate to the same origin again.

Actual behavior

The same prompt reappears for the same origin. The same class of issue also appears for Browser Use upload prompts, where upload to an already allowed origin keeps requiring manual approval.

Observed prompt text examples:

  • Allow Codex to access http://127.0.0.1:8767?
  • Allow upload to https://chatgpt.com/... ?

The persistent selection does not update ~/.codex/browser/config.toml for the new origin, and existing approval_mode = "never_ask" / upload_approval_mode = "never_ask" settings are not honored.

Expected behavior

After the user chooses a persistent allow option, Browser Use should either persist that decision or at least honor the existing ~/.codex/browser/config.toml approval settings. Repeated access to the same origin should not show the same approval popup again.

Local diagnosis

In the affected Browser Use node context, this probe showed that nodeRepl.config was missing:

{
  hasConfig: !!nodeRepl.config,
  readTomlType: typeof nodeRepl.config?.readToml,
  readType: typeof nodeRepl.config?.read,
  readRequirementsType: typeof nodeRepl.config?.readRequirements,
}

Result:

{
  "hasConfig": false,
  "readTomlType": "undefined",
  "readType": "undefined",
  "readRequirementsType": "undefined"
}

The bundled Browser Use runtime appears to call nodeRepl.config.readToml("browser/config.toml") before deciding whether access_browser_origin, upload, download, or history approval is required. When nodeRepl.config is missing, that config path is skipped or falls through, so Browser Use elicits again.

A current-session compatibility bridge that exposed nodeRepl.config.readToml, writeToml, read, and readRequirements from ~/.codex fixed the repeated local-origin prompt in the same session. After installing that bridge, repeated navigation to http://127.0.0.1:8767/index.html and query variants loaded without the origin approval popup.

Additional finding

The cached Browser/Chrome compatibility shim attempted to set __codexBrowserUseElicitationGuardUnavailable on a non-extensible nodeRepl object. That can abort runtime setup before a config bridge has a chance to work:

Cannot define property __codexBrowserUseElicitationGuardUnavailable, object is not extensible

A safe catch around that marker write also fixed local setup in the current session.

Suggested fix direction

  • Ensure the privileged Browser/Chrome runtime always exposes nodeRepl.config in Browser Use node contexts, or have Browser Use fall back to reading ~/.codex/browser/config.toml directly when that object is unavailable.
  • Treat non-extensible nodeRepl objects as normal: failure to set optional guard/debug marker properties should not abort Browser Use setup.
  • Add regression coverage for access_browser_origin and file-transfer approval checks when browser config says never_ask or when [origins] / [uploads] already allow the requested origin.

Related issues / context

This seems related to recent Browser Use state/config instability, but I did not find an exact public issue for repeated access_browser_origin prompts after persistent allow. Potentially adjacent: Browser Use backend/cache instability and approval settings not being honored after app/plugin updates.

View original on GitHub ↗

4 Comments

github-actions[bot] contributor · 3 months ago

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

  • #23014

Powered by Codex Action

jinxiaoliu27-eng · 3 months ago

I also prepared a small public-repo patch that addresses an adjacent MCP elicitation persistence problem visible in this failure mode.

The Desktop bundled Browser/Chrome runtime source does not appear to be present in this public checkout, so this patch is not the full nodeRepl.config fallback fix described above. It does fix the public MCP path where a Guardian/auto-review ApprovedForSession decision is currently returned to the MCP server as a plain one-shot Accept, losing persist=session. For Browser Use style elicitations that support session persistence, that can produce repeated prompts on the auto-review path.

Local branch/commit prepared:

  • branch: codex/preserve-mcp-elicit-session-persist
  • commit: df376ed146aa952d405b915cfcf90d026d96d595

Patch summary:

diff --git a/codex-rs/core/src/session/mcp.rs b/codex-rs/core/src/session/mcp.rs
@@
 use codex_protocol::mcp_approval_meta::CONNECTOR_NAME_KEY as MCP_ELICITATION_CONNECTOR_NAME_KEY;
+use codex_protocol::mcp_approval_meta::PERSIST_KEY as MCP_ELICITATION_PERSIST_KEY;
+use codex_protocol::mcp_approval_meta::PERSIST_SESSION as MCP_ELICITATION_PERSIST_SESSION;
@@
-        ReviewDecision::Approved
-        | ReviewDecision::ApprovedForSession
-        | ReviewDecision::ApprovedExecpolicyAmendment { .. }
+        ReviewDecision::Approved | ReviewDecision::ApprovedExecpolicyAmendment { .. }
         | ReviewDecision::NetworkPolicyAmendment { .. } => ElicitationResponse {
             action: ElicitationAction::Accept,
             content: Some(serde_json::json!({})),
             meta: Some(mcp_elicitation_auto_meta()),
         },
+        ReviewDecision::ApprovedForSession => ElicitationResponse {
+            action: ElicitationAction::Accept,
+            content: Some(serde_json::json!({})),
+            meta: Some(mcp_elicitation_auto_meta_with_persist_session()),
+        },
@@
 fn mcp_elicitation_auto_meta() -> serde_json::Value {
@@
 }
+
+fn mcp_elicitation_auto_meta_with_persist_session() -> serde_json::Value {
+    serde_json::json!({
+        MCP_ELICITATION_APPROVALS_REVIEWER_KEY: ApprovalsReviewer::AutoReview,
+        MCP_ELICITATION_PERSIST_KEY: MCP_ELICITATION_PERSIST_SESSION,
+    })
+}

And the corresponding unit test assertion expects:

{
  "approvals_reviewer": "auto_review",
  "persist": "session"
}

I could not open the PR from this environment because there is no writable fork for this account, the GitHub connector cannot create branches in openai/codex (403 Resource not accessible by integration), and the local environment does not have gh or GitHub HTTPS credentials. Happy to submit the PR once a fork or GitHub CLI auth is available.

jinxiaoliu27-eng · 3 months ago

Follow-up from local reproduction/patch work:

I attempted to open a PR through gh pr create, GitHub REST, the GitHub connector, and the web compare page. The compare page reports that the branch is able to merge, but the upstream repository currently shows: “An owner of this repository has limited the ability to open a pull request to users that are collaborators on this repository.”

So the proposed fix is pushed and available for maintainers, but GitHub is preventing a non-collaborator PR from being opened against openai/codex.

0xdevalias · 1 month ago

I found a potentially deeper explanation for this failure mode in a current macOS Desktop build, though I cannot confirm that it is the cause of this specific report.

One important correction to the earlier diagnostic approach: ordinary model-submitted code receives a deliberately restricted globalThis.nodeRepl without config. Trusted, hash-approved Browser code receives a separate privileged bridge. Therefore, observing globalThis.nodeRepl?.config === undefined from ordinary code does not prove that the privileged bridge is absent.

In my reproduction, I attached a temporary debugger inside the trusted Browser client and observed its two privileged config reads separately:

  • nodeRepl.config.readRequirements() succeeded with { requirements: null }.
  • nodeRepl.config.readToml("browser/config.toml") rejected with Codex TOML directory must not be a symlink.

Here, ~/.codex itself is a symlink. The Browser client catches the exception and fails closed, making persisted Browser settings appear unavailable even though the trusted bridge exists.

I opened https://github.com/openai/codex/issues/35310 with the full evidence:

If an affected installation in this thread uses a symlinked CODEX_HOME/~/.codex, the same rejection may explain its symptoms; otherwise this remains only an adjacent diagnostic finding.

Also related:

  • #30947