[Bug] Chrome extension domain navigation blocked despite domain in approved list
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
- New conversation. Navigate to domain A (in approved sites) → succeeds; A becomes turn-approved.
- Navigate to domain B, also in approved sites → navigate_permission_denied, no prompt.
- 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.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗