[BUG] Desktop Browser pane: a site on the "Allowed sites" list still raises a permission card on every tool call in Auto mode, claiming site permissions are disabled
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?
A site that is on the "Allowed sites" list still raises a permission card on every browser
tool call, and the card claims that permissions for that site are disabled.
What the product promises. Panel settings (the ⋮ button in the Browser pane) -> "Manage
allowed sites" opens the "Allowed sites" dialog, described as:
Claude can use its browser tools on these websites without a permission prompt. Remove a website to be asked again. Only the "Ask" and "Accept edits" modes and financial websites require confirmation per website.
The session met every condition in that sentence: the site was listed, the permission mode was
Auto (not Ask, not Accept edits), and it is an ordinary internal web app, not a financial site.
What happens instead. Every browser tool call raises a card. It offers only "Allow once" —
there is no "Always allow", so the prompting cannot be ended from the card itself. It is not a
read/write distinction: a screenshot and a text extraction are read-only and both prompted.
The UI is German here; the card text is quoted verbatim with a translation below.
What Should Happen?
With the site on the "Allowed sites" list and the session in Auto mode, no permission card
should appear for browser tools on that site — exactly as the dialog's own description states.
If a card is nonetheless correct in some situation the description does not cover, then it
should not claim that "website permissions are disabled" for a site that is on the list, and
it should offer a way to stop asking.
Error Messages/Logs
The card, verbatim (German UI), for a click:
Möchtest du Claude erlauben, Zugriff app-c.intranet.example?
Website-Berechtigungen sind für diese Website deaktiviert. Du wirst für jede Aktion gefragt.
[Ablehnen] [Einmal erlauben]
(Allow Claude to access app-c.intranet.example? Website permissions are disabled for this
website. You will be asked for every action.)
And for a read-only call, where the card names the operation itself:
Möchtest du Claude erlauben, Seiteninhalt lesen auf app-c.intranet.example?
Website-Berechtigungen sind für diese Website deaktiviert. Du wirst für jede Aktion gefragt.
[Ablehnen] [Einmal erlauben]
(Allow Claude to read page content on app-c.intranet.example? Website permissions are
disabled for this website. You will be asked for every action.)
One card per tool call, counted by the user:
mcp__Claude_Browser__navigate -> http://app-c.intranet.example no card
mcp__Claude_Browser__read_page no card
mcp__Claude_Browser__computer (left_click on a footer link) CARD
mcp__Claude_Browser__computer (screenshot) CARD
mcp__Claude_Browser__get_page_text CARD
The stored list at that moment, from preferences.launchPreviewAllowedOrigins in
claude_desktop_config.json:
http://app-a.intranet.example
http://app-b.intranet.example
http://app-c.intranet.example
Steps to Reproduce
The site used here is a plain-HTTP host on a private network with no HTTPS listener. Host names
below are placeholders; the real ones differ but have the same shape.
- Set the session's permission mode to Auto.
- Open the Browser pane and navigate to an internal site, e.g. http://app-c.intranet.example.
Approve the card that appears, choosing "Always allow", so the site lands on the list.
- Open Panel settings (⋮) -> "Manage allowed sites" and confirm the site is listed.
- With the page already open, issue any browser tool call other than navigate or read_page —
a screenshot, or reading the page text.
- A permission card appears, stating that website permissions are disabled for this site, and
offering only "Allow once".
- Repeat step 4. A card appears again, once per call.
Ruled out: a scheme mismatch in the lookup
The obvious benign explanation was that the lookup normalises to https:// while the stored
entry is http://. Several things pointed that way: navigate given a bare host resolves it to
https://, and the "Allowed sites" dialog stores a bare host as https:// too — typingnewentry.intranet.example produced the stored value https://newentry.intranet.example.
Meanwhile the entries created by the "Always allow" card are http://.
Tested directly, and it is not the cause:
a) Through the dialog, app-c.intranet.example was deleted and re-added, leaving the stored
list as:
http://app-a.intranet.example
http://app-b.intranet.example
https://newentry.intranet.example
https://app-c.intranet.example <- https form only; the http entry is gone
b) Without navigating (the tab was already open at http://app-c.intranet.example), a single
get_page_text was issued.
c) The permission card appeared again.
So the card appears whether the site is listed as http:// or as https://. The "Allowed sites"
list has no observable effect on these per-tool-call prompts.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.227
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Other
Additional Information
Environment
Claude Desktop 1.28929.0 (MSIX package) — newest release at the time of filing,
changelog entry dated 2026-08-11
OS Windows 10, 10.0.19044
Permission mode Auto — shown in the composer, and stored as
epitaxy-folder-permission-mode...: { "X:\\projects\\myapp": "auto" }
in claude_desktop_config.json
Site http://app-c.intranet.example, a plain-HTTP host on a private network
with no HTTPS listener
UI language German — cards and labels quoted verbatim with an English translation
Three different notions of what "a site" is
The same feature holds three of them, which may or may not be related to the fault:
- the config stores an origin with a scheme (http://app-c.intranet.example)
- the dialog displays a bare host and de-duplicates by host, so adding
https://app-c.intranet.example while app-c.intranet.example is shown is silently dropped
- a bare host typed into the dialog is stored with https://, regardless of the scheme the
site is actually served over
Because of the second point, the http:// entries that the "Always allow" card creates cannot be
produced through the dialog at all.
Where the config actually lives
The app is packaged as MSIX, so claude_desktop_config.json appears under %APPDATA%\Claude\ from
inside the app but exists on disk only under
%LOCALAPPDATA%\Packages\<package family>\LocalCache\Roaming\Claude\. Anyone reproducing this
from an ordinary shell needs the second path.
Other notes
- Opening the "Allowed sites" dialog and confirming the entry is present does not change the
behaviour — see the check in the steps above.
- The entries carry no port. Whether an origin with a port counts as the same site was not tested.
Possibly related
The changelog for v1.26832.0 (2026-08-06) says:
Removed the "Always allow" option when approving dev server starts in the Browser preview; each new server start now asks, and a server that has crashed asks again instead of restarting silently.
That entry is about dev server starts, not about site permissions — but the card described here
likewise offers only "Allow once". Whether the same removal also affects site-permission cards
is worth checking, because without an "Always allow" the prompting has no exit.
The changelog for 1.28929.0 notes a fix for "some Windows installs (MSIX packages and
enterprise-managed roaming profiles) failing to save chat history, settings, and scheduled
tasks". This install is an MSIX package. Whether site permissions are among the settings that
fix covers is unclear.
#86175 (open) reports preview_start prompting in every permission mode since desktop 1.28929.0
— the same version — with approvals held in memory only. Different code path, but the same
version and the same area of the app.
#84514 (open) asks for a way to opt out of these per-site cards, noting they appear regardless
of permission mode and cannot be pre-approved from settings.
3 Comments
Still present in Claude Desktop 1.30096.1 (changelog entry dated 2026-08-13). Nothing in
that entry addresses this.
Environment unchanged and re-verified before the test:
permission mode Auto (X:\projects\myapp -> "auto")
launchPreviewAllowedOrigins http://app-a.intranet.example
http://app-b.intranet.example
http://app-c.intranet.example <- the site under test
Claude Code version 2.1.229
Re-test, with the site listed and the mode still Auto:
preview_start {url: http://app-c.intranet.example} | one card for the two calls
get_page_text | together
get_page_text (separate call, a few minutes later) | card again
So the per-tool-call prompting is unchanged: a read-only call on a listed site in Auto mode
still raises a card that states website permissions are disabled for that site.
The only difference worth noting is that the first two calls produced a single card between
them rather than one each. Whether the two were coalesced, or
preview_startalone promptedwhile the
get_page_textright after it was covered, cannot be told apart from the outside —the tool result looks identical either way. The standalone
get_page_textafterwards promptedon its own, which is the behaviour originally reported.
Confirming from the reporting side: this is fixed in 1.37937.1. Thank you.
What I can see of the fix, in case it helps anyone arriving here later: the permission card now
offers a host-scoped approval, and the approval is persisted in two config keys that did not
exist before —
"launchPreviewPrivateNetworkReadOrigins": [
"http://app-a.intranet.example",
"http://app-c.intranet.example"
],
"launchPreviewPrivateNetworkReadPins": {
"http://app-a.intranet.example": ["192.168.0.10"],
"http://app-c.intranet.example": ["192.168.0.10"]
}
The approval being pinned to the resolved address makes sense as protection against DNS
rebinding. It also explains the original finding in this report: the "Allowed sites" list never
governed this, because reaching a private-network host is gated separately, and at the time that
gate had no storage behind it. With the host approved, read-only calls now run silently.
---
A follow-up question, not a bug report.
The persisted grant is named
…ReadOrigins, and it does appear to cover reading only. Everyinteracting call on an approved private-network host still raises a card, once per call, with
no option to stop asking.
Measured on 1.37937.1, same session, one call at a time:
call public https site approved private-network host
------------------------ ------------------- -----------------------------
get_page_text no card no card
read_page no card no card
computer (screenshot) no card no card
computer (scroll) no card CARD
computer (left_click) no card CARD
The public site was never added to any list in the config — nothing was written for it at all —
and yet every call including clicks and scrolling ran without a prompt. The private-network host
has a persisted, IP-pinned grant, and still prompts on every interaction.
One caveat on my side: in this environment the private hosts are plain HTTP and the public site
is HTTPS, so "private network" and "plain HTTP" cannot be separated by measurement here. The key
names and the pinned RFC1918 addresses point to the former.
So the question: is a persistent grant for interaction on an approved private-network host
intended to exist, or could one be added? Ideally with the same IP pinning as the read grant,
so the rebinding protection is not weakened. As it stands, working against internal hosts means
a permission card for every click and every scroll, which is the normal case for anyone
developing against an intranet rather than localhost.
Happy to test a change if that is useful.
One more data point, which closes the last question I had about this.
I wondered whether the classification keys off the hostname or the resolved address, so I added
an A record under a public domain I control, pointing at the internal server:
test-host.example.com. IN A 192.168.0.10
Then opened
http://test-host.example.comin the Browser pane. Result: the same card, with thesame wording — "Diese Website befindet sich in einem privaten Netzwerk" ("This website is on a
private network") — and the origin was pinned to the same private address:
"launchPreviewPrivateNetworkReadPins": {
...
"http://test-host.example.com": ["192.168.0.10"]
}
So the decision is made on the resolved IP address space, not on the hostname. That is the
sensible design — a name-based check would be trivially bypassed — and it lines up with how
Chromium classifies private network access generally. No complaint about that part.
The reason I mention it: it means a user has no available way to opt out. Three things are
now ruled out by measurement:
scheme HTTPS with a properly trusted certificate on the internal host no change
tooling the same calls against a public site no cards
hostname a public domain name resolving to the private address no change
The only remaining escape is to move the host into the
localaddress space — an SSH portforward to
localhost— which breaks name-based virtual hosts and is not practical for a serverhosting several sites.
So the question in my earlier comment is not a matter of convenience that could be worked around
with a bit of configuration. For anyone developing against an intranet server rather than
localhost, every click and every scroll needs a confirmation, and there is nothing they can
change on their side to avoid it. A persistent grant for interaction on an already-approved host,
pinned to the address the same way the read grant is, would resolve that without weakening the
protection.
Happy to test any change.