CVE-2026-7989
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifcontent/browser/web_contents/web_contents_view_mac.mm |
modified |
Files Changed
content/browser/web_contents/web_contents_view_aura.cccontent/browser/web_contents/web_contents_view_mac.mm
Patch
From d96c0d8181b6829ef9d9a258080ac87d9b72a72b Mon Sep 17 00:00:00 2001
From: Joel Hockey <joelhockey@chromium.org>
Date: Fri, 24 Apr 2026 13:27:16 -0700
Subject: [PATCH] Disallow reentrant StartDragging() for aura and mac
Bug: 498765082
Change-Id: I6c3cfd64925deb4c8e40f22574226fcc340e9738
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7792498
Auto-Submit: Joel Hockey <joelhockey@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Rakina Zata Amni <rakina@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1620425}
---
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index aca68d7..a71c6b9b 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -1205,6 +1205,10 @@
aura::Window* root_window = GetNativeView()->GetRootWindow();
RenderWidgetHostImpl* const source_rwh =
static_cast<RenderWidgetHostImpl*>(source_rfh.GetRenderWidgetHost());
+ // Disallow reentrant drag which could be an attempt to exploit drag state.
+ if (drag_security_info_.did_initiate()) {
+ return;
+ }
if (!aura::client::GetDragDropClient(root_window)) {
web_contents_->SystemDragEnded(source_rwh);
return;
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm
index ff26bbb..2f4f6d6 100644
--- a/content/browser/web_contents/web_contents_view_mac.mm
+++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -210,6 +210,10 @@
const blink::mojom::DragEventSourceInfo& event_info) {
RenderWidgetHostImpl* source_rwh =
static_cast<RenderWidgetHostImpl*>(source_rfh.GetRenderWidgetHost());
+ // Disallow reentrant drag which could be an attempt to exploit drag state.
+ if (drag_source_start_rwh_) {
+ return;
+ }
url::Origin source_origin = source_rfh.GetLastCommittedOrigin();
// By allowing nested tasks, the code below also allows Close(),
// which would deallocate |this|. The same problem can occur while
@@ -692,6 +696,8 @@
transformed_screen_point.x(), transformed_screen_point.y(),
static_cast<ui::mojom::DragOperation>(drag_operation),
drag_source_start_rwh_.get());
+
+ drag_source_start_rwh_.reset();
}
void WebContentsViewMac::DraggingEntered(DraggingInfoPtr dragging_info,
Original Bug Report
Potential Site Isolation bypass via StartDragging reentrancy in WebContentsViewAndroid
Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the security team.
Overview: A lack of active-drag checks in WebContentsViewAndroid::StartDragging allows a compromised renderer to overwrite the browser’s drag security state. By sending a malicious StartDragging IPC during an active legitimate drag, an attacker can bypass Site Isolation to intercept cross-site drag data and gain unauthorized read access to dropped local files.
Affected files:
content/browser/web_contents/web_contents_view_android.cccontent/browser/renderer_host/render_frame_host_impl.cccontent/browser/renderer_host/render_widget_host_impl.cccontent/browser/web_contents/web_contents_view_drag_security_info.cc
Estimated timestamp from git blame: 2026-01-23
Summary
There is a potential vulnerability in how Android Chrome handles concurrent drag-and-drop operations. Specifically, WebContentsViewAndroid::StartDragging lacks reentrancy guards or checks for an already-active drag. This allows a compromised renderer (e.g., a cross-site iframe) to spam the StartDragging IPC while a legitimate drag from the main frame is ongoing. Doing so overwrites the browser’s internal security state, bypassing the IsValidDragTarget protection (introduced in crbug.com/59081) and allowing the attacker to intercept sensitive cross-site drag data and gain unauthorized file access.
Vulnerability Details
When a drag starts, WebContentsViewAndroid::StartDragging caches the initiating frame’s SiteInstanceGroup ID into drag_security_info_ and calls the Android OS via native_view->StartDragAndDrop(). This cached ID is later used by IsValidDragTarget to ensure that data dragged from one origin cannot be dropped into a cross-origin frame on the same page.
However, because there are no browser-side state checks preventing concurrent StartDragging IPCs, a compromised renderer can send its own StartDragging IPC immediately after a legitimate drag begins. When the browser processes this malicious IPC:
- It unconditionally overwrites
current_source_rwh_for_drag_with the attacker’sRenderWidgetHostImpl. - It calls
drag_security_info_.OnDragInitiated, which unconditionally overwrites the cachedsite_instance_group_id_with the attacker’s ID, completely poisoning the security state. - It attempts to call
native_view->StartDragAndDrop()a second time. Because the OS already has an active drag, this returnsfalse.
Crucially, the failure path for StartDragAndDrop calls OnSystemDragEnded, which notifies the renderer but does not reset drag_security_info_. The secure state reset only happens in OnDragEnded, which only fires when the OS successfully finishes a drag.
Consequently, the browser is left with an active legitimate drag, but its security tracker is locked to the attacker’s ID. When the user drops the item onto the attacker’s iframe, IsValidDragTarget compares the target’s ID against the poisoned cached ID. The check passes, and the browser dispatches the drop to the attacker.
Impact
- Site Isolation Bypass: A compromised renderer can exfiltrate sensitive data (text, URLs, images) dragged from other origins within the same WebContents.
- Unauthorized File Access / Partial Sandbox Escape: If the user drags a local file into the browser,
RenderWidgetHostImpl::DragTargetDropcallsGrantFileAccessFromDropData. Because the drop was erroneously validated, the browser explicitly grants the attacker’s renderer process read access to the local file viaChildProcessSecurityPolicyImpl::GrantReadFile. - Denial of Service: Overwriting
current_source_rwh_for_drag_prevents the victim frame from receiving theDragSourceEndedAtevent, leaving the frame permanently suppressing input.
Suggested Exploitation Steps
(Note: These are potential steps based on code analysis; our tooling agent cannot execute working exploits.)
- Navigate to
https://victim.com, which embeds a cross-site iframe fromhttps://attacker.com. - Assume the
attacker.comrenderer process is compromised and can send arbitrary Mojo IPCs. - The user starts a physical drag operation on a sensitive element in the
victim.commain frame. - The browser process begins the drag and caches the SiteInstanceGroup ID for
victim.com. - The compromised
attacker.comrenderer immediately sends ablink::mojom::LocalFrameHost::StartDraggingIPC to the browser. - The browser unconditionally processes the IPC, overwriting the cached SiteInstanceGroup ID with
attacker.com’s ID. The subsequent OS drag call fails, but the poisoned state persists. - The user drops the item onto the
attacker.comiframe. - The browser’s
IsValidDragTargetcheck passes because the state now matches the attacker’s ID. - The
attacker.comrenderer receives the victim’s drag data and any associated file access grants.
Suggested Fix
- Add Active Drag Checks: In
WebContentsViewAndroid::StartDragging(and potentially other platform implementations), check if a drag is already active before processing a newStartDraggingrequest. If an OS drag is in progress, reject the incoming IPC or ignore it. - Robust Cleanup: Ensure that if
native_view->StartDragAndDrop()fails, the resulting cleanup (e.g.,OnSystemDragEnded) properly resetsdrag_security_info_by callingdrag_security_info_.OnDragEnded()to clear the poisoned state.
Evaluated with Chrome root at commit: ff3d2b74fa39431785bd60e51463b08fcc71ee33
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. And please feel free to reach out to me directly if you have concerns or feedback on the project.