Browser pane: window.open returns null from cross-site iframes (breaks OAuth popups in preview apps)

Open 💬 0 comments Opened Jul 11, 2026 by yyjhao

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.open does 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 computer tool don't carry user activation, so an agent can never open popups — if intentional, worth documenting.

View original on GitHub ↗