Browser pane: window.open returns null from cross-site iframes (breaks OAuth popups in preview apps)
Summary
In the Claude Desktop Browser pane, window.open(...) returns null when called from a cross-site iframe whose top-level page is a real (non-loopback) HTTPS origin — even with live user activation, for any target/features/window-name. The identical call opens in regular Chrome, opens from the top frame, opens from srcdoc/same-origin iframes, and opens when the top page is localhost. This breaks popup-based OAuth (Google, etc.) for any app rendered inside a cross-site iframe — e.g. web-IDE / app-builder live previews and embedded third-party apps.
The desktop docs state: "You can sign in to sites in the pane, including popup sign-in flows such as Google OAuth." That holds for top-level pages but not for iframe-embedded apps served cross-site.
Environment
- Claude Desktop (macOS 15), Code tab Browser pane
- Pane UA:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Claude/1.20186.0 Chrome/148.0.7778.271 Electron/42.5.1 Safari/537.36 - Reproduces on the latest build (persisted across a Claude Desktop update).
Exact condition (measured with real user clicks; navigator.userActivation.isActive === true at each call)
| Top-level page | Initiating frame | window.open result |
|---|---|---|
| http://localhost (loopback) | cross-site iframe (127.0.0.1 or real HTTPS b.example) | opens |
| real HTTPS site a.example | srcdoc iframe (opaque or same-origin), sandboxed w/ allow-popups | opens |
| real HTTPS site a.example | top frame (direct click) | opens |
| real HTTPS site a.example | cross-site real-HTTPS iframe b.example (sandbox incl. allow-popups allow-popups-to-escape-sandbox) | null |
| real HTTPS site a.example | cross-site iframe asks the parent (top frame) to window.open via postMessage | null |
So the block manifests in exactly one shape: a real (non-loopback) HTTPS top page embedding a cross-site real-HTTPS iframe. srcdoc/same-origin iframes and any loopback top page are exempt. No exception is thrown — window.open just returns null. Chrome opens the popup in every row.
Notably, relaying the open to the top frame does not help: when the sandboxed iframe postMessages the (non-sandboxed) parent and the parent calls window.open in its message handler, it also returns null (the iframe click's transient activation doesn't carry across the postMessage task). So apps/embedders cannot work around this.
Minimal repro
Two files on two different real HTTPS origins that are cross-site to each other (loopback/HTTP origins are exempt — do not use localhost).
repro-parent.html (serve on origin A, e.g. https://a.example):
<!doctype html><meta charset="utf-8">
<iframe src="https://b.example/repro-child.html"
sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox"
style="width:360px;height:120px;border:2px solid red"></iframe>
repro-child.html (serve on origin B, e.g. https://b.example):
<!doctype html><meta charset="utf-8"><body>
<button id="b">window.open</button>
<script>
document.getElementById("b").onclick = function () {
var w = window.open("https://example.org", "_blank", "width=500,height=600");
this.textContent = w ? "OPENED" : "NULL (blocked)";
};
</script></body>
Open https://a.example/repro-parent.html in the Browser pane, click the button in the iframe → w is null. Regular Chrome → opens.
(Verified live by instrumenting a shipping product's OAuth window.open inside its cross-site sandbox iframe — the app's own call returned null with activation:true — and reproduced independently with a purpose-built cross-site iframe on the same origin as the app's frame. It does NOT reproduce with a localhost top page or srcdoc iframes, which is how we isolated the condition.)
Expected
Match Chrome: a user-activated window.open from a cross-site iframe with allow-popups/allow-popups-to-escape-sandbox should return a WindowProxy and open the popup (a tab is fine), regardless of whether the top page is loopback or a real HTTPS site.
Impact
Every app-builder / web-IDE that renders the app-under-construction in a cross-site sandboxed iframe (a very common architecture) cannot let users test popup-based OAuth from the in-pane preview — even though the same app works when opened top-level (published). There is no app-side workaround (parent relay also fails).
Additional notes (possibly by design)
- When
window.opendoes succeed (top frame, loopback,srcdoc), the popup opens as a background tab. OAuth mechanics work, but users routinely miss that anything opened and assume it was blocked — fronting the tab or showing an affordance would help. - Synthesized clicks from the agent's
computertool don't carry user activation, so an agent can never open popups — if intentional, worth documenting.