[BUG] Claude in Chrome: mouse input and all DOM tools (find/read_page/form_input/javascript_tool) never reach cross-origin iframes (OOPIFs) — embedded Shopify apps undrivable
Summary
On pages that embed a cross-origin iframe (out-of-process iframe / OOPIF), the Claude in Chrome extension cannot drive the frame: mouse actions never reach it, and every DOM-based tool only sees the top document. Only screenshots and keyboard events cross the boundary.
This makes every embedded Shopify app (the entire Shopify admin app surface, admin.shopify.com/store/<shop>/apps/<handle>) undrivable, since the app is a cross-origin iframe (<iframe name="app-iframe">) inside the admin. The same applies to any admin/SaaS product that hosts third-party UI in an iframe.
Related: #85779 reports the inverse split on Chrome 151 (clicks work, typing fails). On Chrome 152 / extension 1.0.91 I observe the opposite (typing works, clicks fail). Both come from the same cause: the extension only ever talks to the tab-level target.
Environment
- Claude Code CLI (macOS 15, Darwin 25.5)
- Claude in Chrome extension 1.0.91
- Google Chrome 152 (default site isolation)
- Extension site access: "On all sites" (
explicit_host: <all_urls>,withholding_permissions: false)
Repro
- Open any Shopify admin with an embedded app installed, e.g.
https://admin.shopify.com/store/<shop>/apps/<handle>. The app renders in<iframe name="app-iframe">on the app's own origin. computer screenshot→ the frame content is visible.find "buttons inside the app"→ returns only admin-shell elements (sidebar links). App content never appears.read_page,get_page_text,form_input, ref-targeted clicks: same.computer left_clickon a button inside the frame (coordinates taken from the screenshot) → tool reports success, nothing happens.computer scrollat frame coordinates → nothing scrolls.computer key Tab(x3) → focus moves onto buttons inside the app (focus ring visible in the next screenshot). Keyboard does cross the boundary.
Diagnosis
Instrumented the top document with javascript_tool:
['pointerdown','mousedown','mouseup','click'].forEach(t =>
document.addEventListener(t, e => console.log('EV', t, e.clientX, e.clientY, e.target.tagName), true));
Then left_click at a point inside the iframe:
EV pointerdown 525 375 IFRAME
EV mousedown 525 375 IFRAME
EV mouseup 525 375 IFRAME
EV click 525 375 IFRAME
The synthetic mouse events are delivered to the parent document with the <iframe> element as target. A real user click at the same point would go straight to the child renderer and the parent would see nothing. So Input.dispatchMouseEvent issued on the tab-level chrome.debugger session is not being routed into the OOPIF.
Coordinate scaling is not the problem: a top-frame probe at screenshot (100, 650) produced clientX/Y = 114, 743, matching the 1512px screenshot vs 1728 CSS px viewport ratio, and top-frame clicks work.
From the extension bundle (assets/mcpPermissions-*.js):
- Mouse/keyboard:
chrome.debugger→Input.dispatchMouseEvent/Input.dispatchKeyEvent/Input.insertTexton the tab target. NoTarget.setAutoAttach, noTarget.attachToTarget, no per-session dispatch anywhere in the bundle. read_page/find/form_input/ ref clicks:chrome.scripting.executeScript({ target: { tabId } })with noallFrames/frameIds. Theaccessibility-tree.jscontent script is declared withall_frames: true, sowindow.__generateAccessibilityTreeexists in every frame, but it is only ever invoked in the top frame and never descends into iframes (not even same-origin ones).javascript_tool:Runtime.evaluateon the tab session → top frame only.read_console_messages: events from the tab session only; the frame's console is invisible.
Permissions cannot fix it: the extension's own site permission is keyed on the top-level tab URL (admin.shopify.com), the iframe origin is never prompted, and Chrome host access is already <all_urls>.
Expected
The extension should treat OOPIFs like Puppeteer/Playwright do:
Target.setAutoAttach { autoAttach: true, flatten: true, waitForDebuggerOnStart: false }on the root session and trackTarget.attachedToTarget→sessionIdper frame (recursively).- Route
Input.*to the session that owns the frame under the pointer (mouse) or the focused frame (keyboard), or let the browser-side router do it consistently. read_page/find/form_input/ ref clicks: run the tree generator withallFrames: true(or perframeIds), merge results with a frame prefix on refs, and translate ref coordinates by the frame's bounding rect in the parent.javascript_tool: accept an optional frame selector, or at least document that it is top-frame only.read_console_messages: include attached frame sessions.
Workarounds tried
- Keyboard-only driving (Tab / Enter / type) with screenshots works but is impractical for complex UIs.
- Running the app top-level is not an option for Shopify apps: App Bridge (session tokens, resource picker, save bar, nav menu) only works inside the admin frame.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗