Medium watch CVSS 8.3 chrome UAF 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
8.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Navigation
DescriptionUse after free in Navigation
ComponentNavigation
Bug ClassUAF
Action tierwatch — corruption primitive but gated (uncommon) — not default-reachable
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker496463315
Fix commit1ccd3deae8cc (chromium/src) +86/-1
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle
Reported2026-03-26 (per vendor advisory)
Fix landed2026-03-28 (public git)
Disclosed2026-05-05
Patch gap38 days — fix public in source before the advisory

Background

Inner WebContents / inner delegate
a nested WebContents (e.g. the PDF viewer MimeHandlerView) attached into a placeholder subframe of an outer page; attachment proceeds through states tracked by AttachToInnerDelegateState.
`PrepareForInnerWebContentsAttach` phase
an early, asynchronous “preparing to attach” step that runs beforeunload handlers before the real attachment in WebContents::AttachInnerWebContents() / SwapOuterDelegateFrame().
Unload ACK / `OnUnloadACK`
the IPC handler invoked when a renderer reports its frame unloaded; for inner-delegate cases it can call RenderFrameDeleted(), dissociating the RenderFrameHostImpl from its live RenderFrame.
`is_attaching_inner_delegate()` vs `is_inner_delegate_attached()`
the former is true from the start of the prepare phase (state != NONE); the latter, added by this patch, is true only once state reaches ATTACHED.

Root Cause Analysis

OnUnloadACK() (named in the commit message and regression test; the @@ -7061 header does not name the enclosing function) decided whether to treat an unload ACK as a legitimate inner-delegate unload by checking owner->GetRenderFrameHostManager().is_attaching_inner_delegate(). That predicate is already true during the early PrepareForInnerWebContentsAttach phase — before the attachment has actually begun and before any Unload IPC has been sent — so a renderer could send a spoofed unload ACK in that window and drive the browser into the RenderFrameDeleted() branch even though no unload was pending. Calling RenderFrameDeleted() prematurely dissociates/destroys the RenderFrame association while the asynchronous attachment is still in flight, leaving the in-progress attachment operating on a frame that has been torn down — a use-after-free condition in the browser process.

The fix narrows the predicate to is_inner_delegate_attached() (state == ATTACHED), so RenderFrameDeleted() only runs after the attachment has genuinely completed, which — as the commit notes — is the only point where a legitimate unload ACK can arrive (the Unload IPC is sent in SwapOuterDelegateFrame() in the same task that sets the completed state). This is a tightening of the guard.

Key insight
The handler accepted an unload ACK as legitimate during the mere “preparing to attach” phase (is_attaching_inner_delegate()), letting a compromised renderer spoof it and trigger premature RenderFrameDeleted(); the fix requires the stricter is_inner_delegate_attached() (fully ATTACHED) state before that teardown runs.

Attack Path

  1. Start inner-delegate attachment A navigation to a PDF (MimeHandlerView) begins attaching an inner WebContents to a placeholder subframe, entering the async PrepareForInnerWebContentsAttach phase that runs beforeunload.
  2. Widen the window A compromised renderer registers a beforeunload handler on the placeholder subframe so the browser lingers in the prepare phase waiting for the beforeunload ACK (as the regression test does).
  3. Spoof the unload ACK While in that phase, the renderer sends a DidUnloadRenderFrame/unload ACK IPC even though the browser is not actually waiting for one.
  4. Premature teardown Pre-patch, OnUnloadACK() sees is_attaching_inner_delegate() as true and calls RenderFrameDeleted(), dissociating/destroying the RenderFrame mid-attachment.
  5. Use-after-free The still-running attachment then operates on the torn-down frame, yielding a browser-process use-after-free (the specific freed-object dereference is inferred; the diff and advisory establish the UAF class and the premature deletion).

Impact Assessment

A compromised or misbehaving renderer could spoof an unload ACK during inner-delegate attachment to force a premature RenderFrameDeleted(), causing a use-after-free in the browser process. Preconditions are an in-progress MimeHandlerView/inner-WebContents attachment (e.g. navigating to a PDF) and a renderer able to emit the spoofed IPC. The vendor advisory rates this medium (use-after-free in Navigation) and does not report exploitation in the wild; any escalation to code execution beyond the UAF is (inferred).

Changed Functions

FunctionChangeNotes
EXPECT_TRUE
content/browser/security_exploit_browsertest.cc
modified
BeginNavigationTransitionReplacer
content/browser/security_exploit_browsertest.cc
modified

Files Changed

  • content/browser/renderer_host/render_frame_host_impl.cc
  • content/browser/renderer_host/render_frame_host_manager.h
  • content/browser/security_exploit_browsertest.cc

Audit Directions

  • State predicates that are too broad
    Audit IPC handlers that gate destructive actions (frame/object deletion) on “in progress” style predicates; prefer a terminal/COMPLETE state check so renderer-timed messages cannot trigger teardown early.
  • Unsolicited ACK/IPC acceptance
    Review handlers that act on renderer ACKs without confirming the browser is actually awaiting that ACK (is_waiting_for_*), since a compromised renderer can send them at any time.
  • Async attachment/detachment windows
    Examine multi-phase async flows (inner WebContents, portal/fenced-frame attachment, prerender activation) for lifetime assumptions that hold at completion but not during the intermediate, renderer-observable phases.
From 1ccd3deae8ccccf326c8c67f646cf3101ff114c0 Mon Sep 17 00:00:00 2001
From: Alex Moshchuk <[email protected]>
Date: Fri, 27 Mar 2026 19:47:14 -0700
Subject: [PATCH] Disallow spoofed unload ACKs during inner delegate attachment.

This CL prevents misbehaving renderers that are attaching an inner
WebContents for MimeHandlerView (such as when navigating to a PDF),
from incorrectly triggering RenderFrameDeleted from OnUnloadACK()
while not actually waiting for an unload ACK. This can happen in the
async time window where MimeHandlerView is "preparing to attach",
invoked via RenderFrameHostImpl::PrepareForInnerWebContentsAttach(),
which tries to run beforeunload handlers before proceeding with the
actual attachment via WebContents::AttachInnerWebContents().

To do this, OnUnloadACK() checks that the inner delegate has already
been attached, rather than still preparing to attach, at the time it's
received. This should always be the case in normal cases, as the
attachment process sends the Unload IPC in SwapOuterDelegateFrame()
(to swap the placeholder RenderFrame with a proxy and make it
non-live) and then calls set_attach_inner_delegate_complete() [1] in
the same task.

Another approach that was considered here was to check
`is_waiting_for_unload_ack_` in OnUnloadACK() before proceeding with
RenderFrameDeleted() for inner delegate cases, rather than after. This
didn't work out, as it also required updating
RenderFrameHostImpl::SwapOuterDelegateFrame() to set
`is_waiting_for_unload_ack_` to true, which confuses other
unload-related code (e.g., to later try to take placeholder frames
for an inner WebContents off the RFH pending delete list, which we
don't use for placeholder frames).

[1] https://source.chromium.org/chromium/chromium/src/+/main:content/browser/web_contents/web_contents_impl.cc;l=3373;drc=e28fa5b90bf167ca4f5edaa753106753e1e59a4e

Bug: 496463315
Change-Id: I0bdf4dadfc8b642af39e51a4c8fee9dd3cb8f045
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7707137
Reviewed-by: Charlie Reis <[email protected]>
Reviewed-by: Kevin McNee <[email protected]>
Commit-Queue: Alex Moshchuk <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1606603}
---

diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 8ae223b..914b061 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -7061,10 +7061,19 @@
   // it makes its renderer send this message. `owner_` is non null since this
   // attachment can only happen for subframes and pending deletion is the only
   // case where subframes may have a null `owner_`.
+  //
+  // Note that for MimeHandlerView specifically, the unload ACK can only be
+  // legitimately received after the inner delegate has already been attached by
+  // `RFH::SwapOuterDelegateFrame()`, and should be ignored if it's received
+  // during an earlier MimeHandlerView-specific preparation phase invoked via
+  // `RFH::PrepareForInnerContentsAttach()` (because not ignoring it would later
+  // disrupt the attachment, e.g. by causing the Unload IPC not to be sent).
+  // Hence, it's important to check for `is_inner_delegate_attached()` rather
+  // than `is_attaching_inner_delegate()`.
   RenderFrameHostOwner* owner =
       IsPendingDeletion() ? GetFrameTreeNodeForUnload() : owner_;
   if (!is_main_frame() &&
-      owner->GetRenderFrameHostManager().is_attaching_inner_delegate()) {
+      owner->GetRenderFrameHostManager().is_inner_delegate_attached()) {
     // This RFH was unloaded while attaching an inner delegate. The RFH
     // will stay around but it will no longer be associated with a RenderFrame.
     RenderFrameDeleted();
diff --git a/content/browser/renderer_host/render_frame_host_manager.h b/content/browser/renderer_host/render_frame_host_manager.h
index aba08454..517ecfc 100644
--- a/content/browser/renderer_host/render_frame_host_manager.h
+++ b/content/browser/renderer_host/render_frame_host_manager.h
@@ -719,6 +719,12 @@
     return attach_to_inner_delegate_state_ != AttachToInnerDelegateState::NONE;
   }
 
+  // Returns true if an inner delegate has been fully attached.
+  bool is_inner_delegate_attached() const {
+    return attach_to_inner_delegate_state_ ==
+           AttachToInnerDelegateState::ATTACHED;
+  }
+
   // Called by the delegate at the end of the attaching process.
   void set_attach_inner_delegate_complete() {
     attach_to_inner_delegate_state_ = AttachToInnerDelegateState::ATTACHED;
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index fbbcfca9..b500c32 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -24,6 +24,7 @@
 #include "base/test/bind.h"
 #include "base/test/gtest_util.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/test_future.h"
 #include "base/unguessable_token.h"
 #include "build/build_config.h"
 #include "content/browser/attribution_reporting/attribution_manager.h"
@@ -1859,6 +1860,75 @@
             kill_waiter.Wait());
 }
 
+// Inner delegate attachment for MimeHandlerView has an extra phase in the
+// beginning, invoked via RenderFrameHost::PrepareForInnerContentsAttach(),
+// which currently invokes beforeunload handlers prior to proceeding with
+// normal attachment in AttachInnerWebContents()/AttachGuestPage() in a later
+// task. Ensure that a misbehaving renderer doesn't trigger RenderFrameDeleted()
+// via an unload ACK in that first PrepareForInnerContentsAttach() phase, where
+// we aren't actually expecting that unload ACK.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+                       SpoofUnloadACKDuringInnerDelegateAttach) {
+  // Start on a page with a blank iframe, simulating the normal starting point
+  // of attaching an inner delegate (e.g., for MimeHandlerView) to a placeholder
+  // subframe.
+  GURL main_url(
+      embedded_test_server()->GetURL("a.com", "/page_with_blank_iframe.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+  RenderFrameHostImpl* main_frame = web_contents->GetPrimaryMainFrame();
+  RenderFrameHostImpl* subframe = main_frame->child_at(0)->current_frame_host();
+
+  // Add a beforeunload handler to the blank subframe. This shouldn't ever
+  // happen during the normal inner delegate attachment flow, but a compromised
+  // renderer can still do it. This is not technically necessary for the
+  // renderer to send a spoofed unlock ACK while we're in this phase, but it
+  // makes the time window where this ACK can lead to problems larger and more
+  // practical.
+  // TODO(crbug.com/40249634): Make it impossible for placeholder
+  // frames to trigger beforeunload during inner delegate attachment.
+  subframe->DisableBeforeUnloadHangMonitorForTesting();
+  EXPECT_TRUE(ExecJs(subframe, "window.onbeforeunload = function() {};"));
+
+  // Prepare for inner web contents attach (this simulates MimeHandlerView
+  // creating the PDF inner delegate). This currently triggers the beforeunload
+  // phase.
+  base::test::TestFuture<RenderFrameHost*> future;
+  subframe->PrepareForInnerWebContentsAttach(future.GetCallback());
+
+  // Verify that the subframe is waiting for a beforeunload ACK and also
+  // attaching an inner delegate.
+  EXPECT_TRUE(subframe->is_waiting_for_beforeunload_completion());
+  EXPECT_TRUE(subframe->frame_tree_node()
+                  ->render_manager()
+                  ->is_attaching_inner_delegate());
+
+  RenderFrameHostWrapper observer(subframe);
+
+  // Spoof DidUnloadRenderFrame IPC while waiting for beforeunload ACK.
+  subframe->OnUnloadACK();
+
+  // Ensure the subframe is still live, and its RenderFrame is not deleted.
+  ASSERT_FALSE(observer.IsRenderFrameDeleted());
+
+  // Check that we're still in the inner delegate attachment phase.
+  EXPECT_TRUE(subframe->frame_tree_node()
+                  ->render_manager()
+                  ->is_attaching_inner_delegate());
+
+  // The RFH shouldn't change when inner delegate attachment is ready to
+  // proceed.
+  EXPECT_EQ(subframe, future.Get());
+
+  // Make sure proceeding with the inner WebContents attachment succeeds.
+  EXPECT_TRUE(CreateAndAttachInnerContents(subframe));
+  EXPECT_TRUE(subframe->frame_tree_node()
+                  ->render_manager()
+                  ->is_inner_delegate_attached());
+}
+
 class BeginNavigationTransitionReplacer : public FrameHostInterceptor {
  public:
   BeginNavigationTransitionReplacer(WebContents* web_contents,
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index fbbcfca9..b500c32 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -24,6 +24,7 @@
 #include "base/test/bind.h"
 #include "base/test/gtest_util.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/test_future.h"
 #include "base/unguessable_token.h"
 #include "build/build_config.h"
 #include "content/browser/attribution_reporting/attribution_manager.h"
@@ -1859,6 +1860,75 @@
             kill_waiter.Wait());
 }
 
+// Inner delegate attachment for MimeHandlerView has an extra phase in the
+// beginning, invoked via RenderFrameHost::PrepareForInnerContentsAttach(),
+// which currently invokes beforeunload handlers prior to proceeding with
+// normal attachment in AttachInnerWebContents()/AttachGuestPage() in a later
+// task. Ensure that a misbehaving renderer doesn't trigger RenderFrameDeleted()
+// via an unload ACK in that first PrepareForInnerContentsAttach() phase, where
+// we aren't actually expecting that unload ACK.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+                       SpoofUnloadACKDuringInnerDelegateAttach) {
+  // Start on a page with a blank iframe, simulating the normal starting point
+  // of attaching an inner delegate (e.g., for MimeHandlerView) to a placeholder
+  // subframe.
+  GURL main_url(
+      embedded_test_server()->GetURL("a.com", "/page_with_blank_iframe.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+  RenderFrameHostImpl* main_frame = web_contents->GetPrimaryMainFrame();
+  RenderFrameHostImpl* subframe = main_frame->child_at(0)->current_frame_host();
+
+  // Add a beforeunload handler to the blank subframe. This shouldn't ever
+  // happen during the normal inner delegate attachment flow, but a compromised
+  // renderer can still do it. This is not technically necessary for the
+  // renderer to send a spoofed unlock ACK while we're in this phase, but it
+  // makes the time window where this ACK can lead to problems larger and more
+  // practical.
+  // TODO(crbug.com/40249634): Make it impossible for placeholder
+  // frames to trigger beforeunload during inner delegate attachment.
+  subframe->DisableBeforeUnloadHangMonitorForTesting();
+  EXPECT_TRUE(ExecJs(subframe, "window.onbeforeunload = function() {};"));
+
+  // Prepare for inner web contents attach (this simulates MimeHandlerView
+  // creating the PDF inner delegate). This currently triggers the beforeunload
+  // phase.
+  base::test::TestFuture<RenderFrameHost*> future;
+  subframe->PrepareForInnerWebContentsAttach(future.GetCallback());
+
+  // Verify that the subframe is waiting for a beforeunload ACK and also
+  // attaching an inner delegate.
+  EXPECT_TRUE(subframe->is_waiting_for_beforeunload_completion());
+  EXPECT_TRUE(subframe->frame_tree_node()
+                  ->render_manager()
+                  ->is_attaching_inner_delegate());
+
+  RenderFrameHostWrapper observer(subframe);
+
+  // Spoof DidUnloadRenderFrame IPC while waiting for beforeunload ACK.
+  subframe->OnUnloadACK();
+
+  // Ensure the subframe is still live, and its RenderFrame is not deleted.
+  ASSERT_FALSE(observer.IsRenderFrameDeleted());
+
+  // Check that we're still in the inner delegate attachment phase.
+  EXPECT_TRUE(subframe->frame_tree_node()
+                  ->render_manager()
+                  ->is_attaching_inner_delegate());
+
+  // The RFH shouldn't change when inner delegate attachment is ready to
+  // proceed.
+  EXPECT_EQ(subframe, future.Get());
+
+  // Make sure proceeding with the inner WebContents attachment succeeds.
+  EXPECT_TRUE(CreateAndAttachInnerContents(subframe));
+  EXPECT_TRUE(subframe->frame_tree_node()
+                  ->render_manager()
+                  ->is_inner_delegate_attached());
+}
+
 class BeginNavigationTransitionReplacer : public FrameHostInterceptor {
  public:
   BeginNavigationTransitionReplacer(WebContents* web_contents,
Loading diff…

Original Bug Report

reported by [email protected]

Sandbox Escape: Premature RenderFrameDeleted via spoofed DidUnloadRenderFrame during inner delegate attach

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: A logic flaw in RenderFrameHostImpl::OnUnloadACK allows a compromised renderer to spoof a DidUnloadRenderFrame IPC while the browser is waiting for a BeforeUnload ACK. This bypasses the unload acknowledgment check and prematurely calls RenderFrameDeleted() on an active frame. Observers free associated state while the frame remains in the tree, leading to a potential Use-After-Free (UAF) in the browser process.

Affected files:

  • content/browser/renderer_host/render_frame_host_impl.cc
  • content/browser/renderer_host/agent_scheduling_group_host.cc
  • content/browser/renderer_host/render_frame_host_manager.cc

Estimated timestamp from git blame: 2025-10-27

Summary

A static analysis of content/browser/renderer_host/render_frame_host_impl.cc reveals a potential vulnerability in RenderFrameHostImpl::OnUnloadACK. The function handles the acknowledgement of a frame unloading. However, the logic contains a critical ordering flaw: it checks if the frame is attaching an inner delegate (e.g., loading a PDF via MimeHandlerView) and immediately calls RenderFrameDeleted() before verifying if the browser is actually waiting for an Unload ACK.

A compromised renderer can exploit this by sending a spoofed DidUnloadRenderFrame IPC while the browser is only waiting for a BeforeUnload ACK. This triggers RenderFrameDeleted() prematurely, causing WebContentsObservers to free per-frame state. Because the BeforeUnload timeout is still running and the frame is not detached from the FrameTree, subsequent iterations over the frame tree (e.g., via ForEachRenderFrameHost) will yield this zombie frame, potentially causing observers to access freed state, leading to a Use-After-Free (UAF) in the highly privileged Browser process.

Technical Details

In RenderFrameHostImpl::OnUnloadACK, the code evaluates whether to delete the frame during inner delegate attachment:

void RenderFrameHostImpl::OnUnloadACK() {
  // ...
  RenderFrameHostOwner* owner =
      IsPendingDeletion() ? GetFrameTreeNodeForUnload() : owner_;
  if (!is_main_frame() &&
      owner->GetRenderFrameHostManager().is_attaching_inner_delegate()) {
    // This RFH was unloaded while attaching an inner delegate.
    RenderFrameDeleted();
    return;
  }

  // Ignore spurious unload ack.
  if (!is_waiting_for_unload_ack_) {
    return;
  }
  // ...
}

The is_attaching_inner_delegate() check occurs before the is_waiting_for_unload_ack_ check.

When a subframe navigates to a resource requiring an inner delegate (like a PDF), RenderFrameHostManager::PrepareForInnerDelegateAttach sets the state to PREPARE_FRAME (making is_attaching_inner_delegate() return true). If the subframe has a beforeunload handler, the browser dispatches a BeforeUnload IPC and starts a timeout. Crucially, during this phase, the browser is waiting for a BeforeUnload ACK, so is_waiting_for_unload_ack_ is false.

A compromised renderer can send a DidUnloadRenderFrame IPC for this subframe via AgentSchedulingGroupHost. The browser receives it, calls OnUnloadACK(), hits the is_attaching_inner_delegate() bypass, and prematurely executes RenderFrameDeleted().

Potential Exploitation Steps

(Note: These are suggested steps based on static analysis; a working Proof of Concept has not yet been developed.)

  1. Attacker Setup: A compromised renderer creates an <iframe> and installs a beforeunload event handler on it.
  2. Trigger Attachment: The renderer navigates the iframe to a PDF file, triggering MimeHandlerView creation.
  3. Browser State Change: The browser intercepts the request, the renderer loads the placeholder, and signals ReadyToCreateMimeHandlerView. The browser calls PrepareForInnerDelegateAttach, setting attach_to_inner_delegate_state_ to PREPARE_FRAME.
  4. Dispatch BeforeUnload: Because of the beforeunload handler, the browser dispatches a BeforeUnload IPC to the renderer and starts a 1-second timeout timer. The browser’s is_waiting_for_unload_ack_ state remains false.
  5. Spoof IPC: The compromised renderer intentionally ignores the BeforeUnload IPC. Instead, it sends a spoofed DidUnloadRenderFrame IPC for the iframe.
  6. Premature Deletion: The browser receives the spoofed IPC and calls RenderFrameHostImpl::OnUnloadACK. The logic flaw bypasses the is_waiting_for_unload_ack_ check, directly executing RenderFrameDeleted().
  7. Observer State Freed: RenderFrameDeleted() notifies all WebContentsObservers (e.g., Extensions, Autofill), which proceed to free memory and state mappings associated with this RenderFrameHost*.
  8. Use-After-Free: The frame remains in the FrameTree (the beforeunload timeout is still running). When a downstream browser component iterates the frame tree (e.g., WebContentsImpl::ForEachRenderFrameHost), it yields this zombie RenderFrameHost*. Observers accessing their now-freed state mappings for this pointer will trigger a Use-After-Free (Sandbox Escape).

Suggested Fix

The is_waiting_for_unload_ack_ check should be moved up in RenderFrameHostImpl::OnUnloadACK so that spurious Unload ACKs are rejected before evaluating the inner delegate attachment state.

void RenderFrameHostImpl::OnUnloadACK() {
  // ... (existing early returns)

  // Ignore spurious unload ack MUST happen first.
  if (!is_waiting_for_unload_ack_) {
    return;
  }

  RenderFrameHostOwner* owner =
      IsPendingDeletion() ? GetFrameTreeNodeForUnload() : owner_;
  if (!is_main_frame() &&
      owner->GetRenderFrameHostManager().is_attaching_inner_delegate()) {
    RenderFrameDeleted();
    return;
  }
  // ...
}

Evaluated with Chrome root at commit: 0eb4855bda702feaaa8b899336664f97e3df88b8


Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. Please feel free to reach out to me if you have concerns or feedback.

View on issue tracker