mcp__Claude_in_Chrome__navigate silently denies non-pre-approved domains — no user-facing approval path exists anywhere

Status Open
Maintainer reply None cached
Activity 14 comments · opened Apr 19, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When Claude Code Desktop's mcp__Claude_in_Chrome__navigate tool is called with a domain not in the session's seeded turnApprovedDomains set, the extension silently denies the request with { allowed: false, needsPrompt: false }. No approval prompt surfaces anywhere in the product. No toast, no side-panel control, no UI of any kind.

This breaks any workflow involving per-branch preview URLs (Vercel, Netlify, Cloudflare Pages, Render, etc.) where the target hostname is unique per PR and cannot be known at session start.

The UI scaffolding for the fix already exists at claude.ai/settings/browser-extension — Anthropic has shipped the block-list half of the permission model (blockedUrlPatterns) but not the allow-list half (which would be the UI counterpart to the extension's existing turnApprovedDomains / permissionStorage).

What Should Happen?

One or more of the following:

  1. An allow-list UI at claude.ai/settings/browser-extension symmetric to the existing block-list, with wildcard support (*.vercel.app, *.netlify.app, *.pages.dev, *.onrender.com).
  2. 2. Gate 1 should fall through to { needsPrompt: true } in interactive sessions instead of { allowed: false, needsPrompt: false } — so the user at least gets a visible approval dialog.
  3. 3. An MCP tool the agent can call to request additional domains mid-session, triggering a user-confirmation prompt in Claude Code Desktop.
  4. 4. An allow-list key in the extension's managed_schema.json alongside blockedUrlPatterns.

Error Messages/Logs

Tool call response from mcp__Claude_in_Chrome__navigate:
"Navigation to this domain is not allowed"

No stack trace. No additional detail. The error is returned synchronously with no user-facing prompt or notification of any kind.

Steps to Reproduce

  1. Open Claude Code Desktop (v1.2773.0.0, Windows 11 MSIX) with the Claude in Chrome integration active (extension v1.0.68).
  2. Start a new conversation. Ask Claude to navigate to a Vercel PR preview URL, e.g.: "Go to https://tenefly-bicjcd639-mensahb89s-projects.vercel.app and tell me what you see."
  3. 3. Claude Code Desktop activates follow_a_plan permission mode and seeds turnApprovedDomains with the project's known domains (e.g., ["www.tenefly.com"]) via IPC: { subtype: "set_permission_mode", mode: "follow_a_plan", allowed_domains: ["www.tenefly.com"] }.
  4. 4. Claude calls mcp__Claude_in_Chrome__navigate with the preview URL.
  5. 5. Result: Tool returns "Navigation to this domain is not allowed". No prompt appears anywhere — not in Claude Code Desktop, not in the Chrome extension popup, not as a toast or notification.

Root cause (traced to extension source):

In fcoeoabgfenejglbffodgkkbkcdhcgfn/1.0.68_0/assets/PermissionManager-WI3FAKQw.js, checkPermission() runs:

// Gate 1 — fires before persistent storage and before the prompt fallback
if (r && this.turnApprovedDomains.size > 0 && !this.isTurnApprovedDomain(r))
  return { allowed: false, needsPrompt: false };

When turnApprovedDomains is non-empty, this gate hard-denies any unlisted domain with needsPrompt: false, bypassing both the persistent permissionStorage lookup and the user-approval prompt fallback.

Every path verified as non-working:

  • Editing CLAUDE.md "Browser access" section — not consulted by host plan seeding
  • - Brand-new session with preview URL in the first user message — hostname still not in turnApprovedDomains
  • - - Clicking the Claude in Chrome extension icon — no per-domain approval UI in v1.0.68
  • - - - Chrome managed policy (managed_schema.json) — exposes only blockedUrlPatterns and forceLoginOrgUUID; no allow-list key
  • - - - - claude.ai/settings/browser-extension — full audit performed; exposes only a block-list (binary on/off + blocked sites list). "Default for all sites" dropdown has exactly two options: "Allow extension" and "Block extension". No allow-list, no wildcard field
  • - - - - - Claude Code Desktop CLI (claude --help) — only --chrome/--no-chrome
  • - - - - - - All Claude Code Desktop config files — no browser-domain settings
  • - - - - - - - Editing the extension's permissionStorage LevelDB — irrelevant because Gate 1 fires before that store is consulted
  • - - - - - - - - /org/settings on claude.ai — redirects to homepage (individual Pro account); no org admin console

Claude Model

None

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

1.2773.0.0 (Claude Code Desktop, Windows MSIX). Claude in Chrome extension v1.0.68.

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

Why this hurts

Per-PR preview deployments are table stakes for modern web dev. Our team ships UI changes behind feature flags and needs to visually verify on a Vercel preview URL before merge. Preview hostnames are unique per branch — there is no way to pre-list them at session start.

Viable workarounds attempted:

  • Patching the extension file locally — Chrome hashes extension files and can silently reinstall from cache or flag the extension as corrupted (disabling the whole integration). Not viable.
  • - DevTools monkey-patching the running service worker — MV3 service workers idle-kill after ~30 seconds; the patch is lost on restart. Not viable for tasks longer than a few minutes.
  • - - Merging without preview verification — defeats the verification gate entirely.

Why the fix is low-effort

The backend already fully exists:

  • turnApprovedDomains (in-memory Set) and permissionStorage (LevelDB) are already implemented in the extension
  • - The set_permission_mode IPC path already accepts an allowed_domains array
  • - - claude.ai/settings/browser-extension already has the UI scaffold (block-list side)

Shipping the allow-list side is finishing what's half-built, not net-new infrastructure. Adding wildcard support (*.vercel.app) would unblock all PR preview workflows with a single entry.

Suggested fix preference order

  1. Add allow-list UI to claude.ai/settings/browser-extension with wildcard support — symmetric to the existing block-list
  2. 2. Change Gate 1 from { allowed: false, needsPrompt: false } to { allowed: false, needsPrompt: true } in interactive sessions — at minimum gives the user a visible approval path
  3. 3. Expose an MCP tool for the agent to request additional domains mid-session with user confirmation
  4. 4. Add an allow-list key to managed_schema.json alongside blockedUrlPatterns

Happy to test patches on a preview build and provide additional repro data.

View original on GitHub ↗

13 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/43255
  2. https://github.com/anthropics/claude-code/issues/49979
  3. https://github.com/anthropics/claude-code/issues/43327

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

0xbrainkid · 4 months ago

{ allowed: false, needsPrompt: false } is the worst possible combination here because it creates a silent policy wall with no recovery path.

That means the system has enough logic to deny the action, but not enough product surface to explain the denial or let the user authorize the new domain. For preview-URL workflows that is especially damaging because ephemeral per-branch hostnames are normal, not exceptional.

So the real bug is not only "cannot navigate to some domains." It is that the permission model is half-implemented:

  • block list exists
  • seeded approved domains exist
  • but there is no visible mid-session approval path when reality changes

That turns a dynamic browser tool into a static allowlist tool, which breaks many legitimate dev workflows.

The most important fix is the interactive fallback you suggest: when the session is interactive and the domain is not pre-approved, the extension should surface a real approval request instead of returning a silent denial. Even before a full allow-list UI ships, that would restore operator control.

More broadly, this is another hidden-boundary problem. Users cannot trust tool capabilities if policy denials happen invisibly and indistinguishably from tool flakiness.

DanThorneJ · 4 months ago

I reproduced the error identically on MS Edge with the same v1.0.69 extension installed (deviceId different, error identical: permission_required: subdomain.ourinternalwebsite.com). Confirms the regression is in the extension build, not platform-specific to Chrome.

pya-cyber · 3 months ago

Same issue on macOS — 3+ weeks blocked

  • OS: macOS (Apple Silicon)
  • Claude Desktop: 1.8555.2(a476c3)
  • Claude in Chrome extension: 1.0.72
  • claude.ai/settings/browser-extension: "Allow extension on all sites", no blocked sites
  • Extension settings → 承認済みのサイト (Approved sites): empty, and there is NO "Add site" button in the UI

Symptom:

  • First domain navigated to in a new session works
  • All subsequent navigate calls to different domains return "Navigation to this domain is not allowed"
  • No approval popup ever renders, so the approved sites list stays permanently empty
  • Extension sidebar (chat) itself works fine on all domains
  • claude --chrome-native-host socket bridge is healthy

This has persisted for 3+ weeks and completely blocks multi-site workflows. Please prioritize.

fernandomenendez-qida · 2 months ago

Confirming this is still a problem

athos45 · 2 months ago

+1, same issue here.

Symptoms mcp__Claude_in_Chrome__navigate (and tabs_create_mcp followed by navigate) returns "Navigation to this domain is not allowed" on every domain tested (google.com, infomaniak.com, example.com) — not site-specific.

"Your approved sites" stays empty Checked Claude in Chrome settings → Authorizations → "Vos sites approuvés" ("Your approved sites"): list is empty, and no approval prompt ever renders in the browser or in the side panel to populate it.

Troubleshooting already tried (no effect)

Restarted Chrome
Uninstalled/reinstalled the Claude in Chrome extension with different permissions
Switched browser entirely: Chrome → Brave, same error
Full computer restart
Extension version: 1.0.77
Notable detail Navigation worked once, early in the session (google.com/search?q=... succeeded). After opening the extension's own settings page ("Vos sites approuvés"), every subsequent navigation attempt — including to google.com again — started failing with the same error, and never recovered despite all the troubleshooting above.

Environment

OS: Windows 11 Pro
Browsers tested: Chrome, Brave
Driven via: Claude Code (agent), MCP tools

rajatrocks · 2 months ago

Diagnosis from Claude Code:

Title: claude-in-chrome navigate silently locks to first domain of a conversation, shadowing the saved approved-sites allowlist

Environment

  • Claude Code MCP server: claude-in-chrome
  • Chrome extension fcoeoabgfenejglbffodgkkbkcdhcgfn (Claude for Chrome) v1.0.77
  • macOS, Chrome (Default profile)

Summary
Once any domain is approved during a conversation, mcp__claude-in-chrome__navigate hard-denies every other domain — even domains that are explicitly ALLOW in the extension's persisted permissionStorage (the "approved sites" UI list). No permission prompt is offered, so there's no recovery within the conversation. Effect: the first domain navigated in a conversation becomes the only usable domain for the rest of that conversation.

Root cause (from assets/mcpPermissions-CJK8I7C7.js)
// checkPermission():
if (n && this.turnApprovedDomains.size > 0 && !this.isTurnApprovedDomain(n))
return { allowed: false, needsPrompt: false }; // ← hard deny, no prompt
...
if (!this.forcePrompt && this.isTurnApprovedDomain(i))
return { allowed: true, needsPrompt: false };
await this.loadPermissions(); // permissionStorage only checked here (unreachable once locked)
turnApprovedDomains is an exclusive in-session lock set via setTurnApprovedDomains(). Once non-empty, the short-circuit returns needsPrompt:false, so (a) permissionStorage is never consulted, and (b) no prompt is raised to approve the new domain. The caller (navigate) then returns:
{ error: "Navigation to this domain is not allowed", errorCode: "navigate_permission_denied" }

Repro

  1. New conversation. Navigate to domain A (in approved sites) → succeeds; A becomes turn-approved.
  2. Navigate to domain B, also in approved sites → navigate_permission_denied, no prompt.
  3. permissionStorage shows both A and B as {action:"allow", duration:"always"} with identical schema.

Observed invariants while debugging

  • Only the first-used domain works; all other approved sites blocked.
  • Editing/restoring chrome.storage.local.permissionStorage has no effect (enforcement doesn't read it once locked).
  • Extension holds <all_urls> host permission, so Chrome isn't the gate.
  • Persists across new MCP tab groups, SW reload, an SW-reload-induced Chrome crash, and a full cold restart — because the MCP client (Claude Code) keeps running and re-pushes the turn-approved set on reconnect.
  • tabGroups[<id>].domain and turnApprovedDomains are the live enforcement state; permissionStorage is effectively display-only here.

Expected
When turnApprovedDomains is non-empty and a different domain is requested, either (a) fall through to permissionStorage and allow if ALLOW, or (b) return needsPrompt:true so the user can approve the additional domain. The persisted approved-sites list should not be silently shadowed.

Secondary bug
Reloading the extension's service worker (chrome.runtime.reload() from its DevTools) crashed Chrome — suggests the SW init path throws/loops under some state.

Workaround
One external domain per conversation, navigated first; start a fresh conversation to use a different domain.

kidneyman10 · 1 month ago

Corroborating report on macOS, with the org-policy layer explicitly ruled out.

Setup: Claude Desktop driving mcp__claude-in-chrome__navigate through the Claude in Chrome extension. macOS, single local browser connected. The account is the organization Owner.

Trace (matches @rajatrocks's "locks to the first domain of the conversation"):

  1. Early in the conversation I navigated to my own staging site and approved its one-time permission prompt. Worked fine.
  2. Later in the same conversation, navigate to a second domain (www.printful.com) returned Navigation to this domain is not allowed, with no prompt anywhere (no toast, no side-panel control, no dialog).
  3. Every other domain in that conversation is then denied. Only the first-approved domain keeps working.

Ruled out, so this is clearly not a config or policy problem:

  • Org policy is permissive: as Owner, claude.ai -> Settings -> Claude in Chrome shows "Default for all sites = Allow extension" ("works everywhere except sites you block below") with an empty blocklist.
  • Chrome host access is "On all sites."
  • Local .claude/settings.local.json has no domain restriction; the chrome MCP tools are permitted generally.
  • The interactive side panel reaches any site (consistent with the permissive policy). Only the MCP navigate path is locked.

So even on a fully-permissive Owner account, MCP navigation hard-locks to the first domain approved in the conversation and denies all others with {allowed:false, needsPrompt:false}. Starting a fresh conversation and navigating to the desired domain first confirms it (that domain then works and the previous one is locked out). The mid-session approval prompt, or the agent-callable request-domain tool proposed in the original post, would resolve this.

aoisyzn-ops · 1 month ago

Additional data point from Windows 11 that narrows the trigger, plus a workaround not yet mentioned in this thread.

The session lock is seeded by answering "Always allow" on the session's first browser navigate permission prompt.

Environment: Claude desktop app 1.18286.0 (MSIX), Claude Code CLI 2.1.197 (entrypoint: claude-desktop), extension v1.0.79, Chrome stable, Windows 11 Home.

  • If the first browser:navigate prompt in a session is answered "Always allow": that domain becomes the only usable domain for the rest of the session. Every other domain — including example.com and wikipedia.org — returns Navigation to this domain is not allowed with needsPrompt:false. The desktop app's main.log confirms no permission request is even emitted after the first one.
  • If the first prompt is answered "Allow once": the lock never engages — every new domain prompts normally. We navigated mail.google.com → github.com → railway.app in a single session with no denials (each domain prompted once).

So the most trusting answer ("Always allow") produces the most restricted session, while "Allow once" preserves full multi-domain functionality. Workaround for anyone hitting this: always answer "Allow once" on browser permission prompts.

One more observation: a second machine on the same account with the same app + extension versions never exhibits the lock. The affected machine started showing it immediately after the desktop app was reset/reinstalled on 2026-07-02 — possibly a staged rollout / flag difference on the client side that enables the follow_a_plan seeding described in the OP.

aoisyzn-ops · 1 month ago

Follow-up — the machine-to-machine difference from my previous comment is now explained, and it's much simpler than the staged-rollout theory I speculated about.

The lock only engages when the Claude Code session's permission mode is the default "approve" mode. In auto-accept mode the lock never engages — and switching the mode mid-session releases an already-locked session immediately.

Decisive test (Windows 11, desktop app 1.18286.0, extension v1.0.80): a session that had been hard-locked to github.com for days (mail.google.com / railway.app / example.com all returning Navigation to this domain is not allowed) was unlocked by nothing more than switching the session's permission mode from "approve edits" (default) to "auto". Same session, same extension, no restart — immediately after the switch, example.com, mail.google.com and railway.app all navigated (and screenshotted) fine.

This also resolves my earlier "second machine never exhibits the lock" observation: that machine habitually runs in auto mode — no rollout/flag difference required. And the machine that "suddenly broke" had been reset, which reverted its permission mode to the default.

Practical guidance for anyone hitting this:

  • Instant fix: switch the session's permission mode to auto — works mid-session, releases the lock immediately
  • If you need to stay in the default approve mode: answer "Allow once" (not "Always allow") on browser permission prompts

The underlying bug from the OP is still present in extension v1.0.80 (Gate 1 hard-deny with needsPrompt:false is unchanged in mcpPermissions-*.js) — approve mode still silently denies unlisted domains with no approval path.

MCTheDOC · 1 month ago

Same bug, +1 — with a repro matrix that isolates it to the MCP bridge's internal allowlist

Environment: Claude in Chrome v1.0.80, Chrome on Ubuntu (also reproduced identically with the extension in Edge on Windows 11). Driven from Claude Code via the claude-in-chrome MCP tools.

Setup (everything a user can configure is maxed out):

  • Chrome extension Site access: "On all sites"
  • Side panel mode: "Act without asking"
  • Extension Options → Permissions → "Your approved sites": empty, and there is no control to add a site manually

What works:

  • The side-panel agent browses and clicks on site-b.example.com with no issue (so the extension itself has full access to the site).
  • MCP tools work fine on site-a.example.com — a domain that got approved at some point in the past, proving the MCP bridge allowlist exists and is honored.

What's broken — MCP tools refuse site-b.example.com in every form:

  • navigateNavigation to this domain is not allowed (instant, no approval prompt anywhere — not in the browser, not in the side panel, not in the Claude Code client)
  • computer (screenshot) on an already-open tab for that domain, moved into the MCP tab group → Permission denied for this action on this domain

Things that do NOT register a domain for the MCP bridge (all tried):

  • Completing a side-panel task on the site (including tasks that perform clicks)
  • Setting the side panel to "Act without asking"
  • Chrome extension site access "On all sites"
  • Reinstalling / signing the extension out and back in on a second machine

Expected: either MCP calls to a new domain trigger the site-approval prompt (like the side panel gets), or the Options page's "Your approved sites" list is manually editable. Currently there is no path whatsoever for a user to grant the MCP bridge a new domain, while domains approved earlier (mechanism unknown) keep working — which matches #58464 and #61611.

acglay · 1 month ago

Adding another data point with a fairly complete repro / isolation trail (Windows 10, Claude Code desktop app + Claude in Chrome extension).

What happened

  • The extension worked fine for several days driving suno.com and gemini.google.com from Claude Code sessions (navigate / computer / read_page all OK, site approvals accumulated normally).
  • After reloading the extension (and later a full reinstall + PC reboot), list_connected_browsers shows a new deviceId, and every page-level action is now rejected:
  • navigate → "Navigation to this domain is not allowed" (all domains — even example.com, so not site-specific)
  • computer (screenshot) → "Permission denied for this action on this domain"
  • Tab-level ops still work fine (tabs_context_mcp, tabs_create_mcp, list_connected_browsers).

Key observations

  1. No approval prompt ever fires for Claude Code-originated actions. Tested with the target tab focused and the side panel closed — rejection is instant, no banner/dialog anywhere.
  2. Extension settings → Permissions → "Your approved sites" shows empty ("no approved sites yet") and there is no way to add sites manually.
  3. Chrome-level site access for the extension is set to "On all sites".
  4. The side panel's own agent works: asking it to screenshot the Gemini tab produces a plan-approval card ("Allow actions on gemini.google.com"), and after approving, the side-panel agent can act. That approval does not propagate to the external Claude Code connection — same domain still rejected.

So approvals appear to be keyed to the connection/device identity: reloading the extension rotates the deviceId, orphans all prior approvals, and the re-approval prompt for external (Claude Code) connections never triggers — leaving no recovery path other than abandoning the extension for that workflow.

Happy to provide logs or run diagnostics if useful.

rajivpant · 1 month ago

Corroborating from a different angle: the same root problem (unique-per-deploy origin defeats a per-origin trust model) also surfaces as a visible, unavoidable-per-visit prompt — 'Allow Claude to act on [URL]?' with Deny/Always allow/Allow once — rather than a silent deny, on a Cloudflare Pages preview URL (<hash>.<project>.pages.dev). Possibly a different tool/code path than mcp__Claude_in_Chrome__navigate, but the underlying gap (no wildcard/pattern pre-auth for auto-generated preview domains) is the same, so a fix should cover both manifestations.

Showing cached comments. Read the full discussion on GitHub ↗