Reverse Engineering

Out-of-Process Iframes (OOPIF): Why Hooks Miss Sandboxed Widgets

By the Scrappey Research Team

Out-of-Process Iframes (OOPIF): Why Hooks Miss Sandboxed Widgets — conceptual illustration
On this page

An out-of-process iframe (OOPIF) is a cross-origin frame that Chromium runs in its own renderer process, with its own isolated JavaScript context. Because it is a separate process, a hook you inject into the top page does not exist inside it. This is exactly why instrumentation aimed at the main frame goes blind the moment a sandboxed widget -- like a CAPTCHA or bot-check frame -- does its real work inside an OOPIF.

Quick facts

What it isA cross-origin iframe in its own renderer process
Driven bySite Isolation (per-site processes)
ProblemTop-frame injection does not reach the child process
Real exampleCAPTCHA / bot-check widgets run inside an OOPIF
FixAttach to each target via Target.attachedToTarget

Site Isolation splits the page into processes

Chromium's Site Isolation puts cross-origin frames in separate renderer processes for security. A page at example.com embedding a widget from challenges.cloudflare.com is now two processes, two JavaScript contexts. Your pre-load hook was injected into the top frame's process; the widget's process never saw it. So when a Turnstile widget runs its canvas fingerprinting inside that frame, your instrumentation records nothing.

Attaching to every target

The CDP fix is to treat each frame as its own debuggee. With auto-attach enabled, the browser fires a Target.attachedToTarget event whenever a new target (including an OOPIF) appears. You handle that event, get a session for the child target, and re-run your injection into it -- so the hook follows the widget into its own process. Without this, OOPIF widgets are a permanent blind spot.

Why visibility is not the whole problem

Per-target attachment solves visibility but not the observer-effect problem. You can now observe inside the widget, but the hooks you install there are still JavaScript wrappers that fail a toString check, and the act of attaching to many targets is itself a signal in CDP detection. A widget specifically built to resist analysis assumes someone is attaching. The only way to observe it without leaving a JavaScript-visible trace that the widget can react to is to move the observation point into the engine for every frame at once.

Code example

javascript
// CDP: follow hooks into out-of-process iframes.
await cdp.send('Target.setAutoAttach', {
  autoAttach: true,
  waitForDebuggerOnStart: true,
  flatten: true,
});

cdp.on('Target.attachedToTarget', async ({ sessionId, targetInfo }) => {
  // A new frame appeared in its own process (e.g. a bot-check widget).
  // Re-inject the same pre-load hook into THIS target's session:
  await cdp.send('Page.addScriptToEvaluateOnNewDocument',
    { source: HOOK_SOURCE }, sessionId);
  await cdp.send('Runtime.runIfWaitingForDebugger', {}, sessionId);
});

Related terms

Concept map

How Why Do JS Hooks Miss Out-of-Process Iframes (OOPIF) connects

The terms most directly tied to this one. Hover a node to see its neighbours, click to preview, drag to rearrange.

0 terms · 0 connections
You are here · Reverse Engineering
Building map…

Frequently asked questions

Why does Chromium run iframes in separate processes?

It is called Site Isolation. Putting cross-origin frames in their own renderer processes limits the damage of a compromised renderer and enforces stronger boundaries between sites -- at the cost that a single page is now many processes.

Do all iframes become OOPIFs?

No. Same-origin iframes typically share the parent's process. Cross-origin frames are the ones promoted to out-of-process, which is why third-party widgets and CAPTCHAs are the usual blind spots for top-frame hooks.

How do automation tools reach into OOPIFs?

They enable CDP auto-attach and handle Target.attachedToTarget, creating a debugger session per frame and re-injecting their scripts. This makes child frames visible but does not hide the instrumentation from the page.

Last updated: 2026-06-09