Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient data validation in DataTransfer
DescriptionInsufficient data validation in DataTransfer
ComponentDataTransfer
Bug ClassLogic Error
Tracker498765082
Fix commitd96c0d8181b6 (chromium/src) +10/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-05

Changed Functions

FunctionChangeNotes
if
content/browser/web_contents/web_contents_view_mac.mm
modified

Files Changed

  • content/browser/web_contents/web_contents_view_aura.cc
  • content/browser/web_contents/web_contents_view_mac.mm
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,
Loading diff…

Original Bug Report

reported by vm...@google.com

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.cc
  • content/browser/renderer_host/render_frame_host_impl.cc
  • content/browser/renderer_host/render_widget_host_impl.cc
  • content/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:

  1. It unconditionally overwrites current_source_rwh_for_drag_ with the attacker’s RenderWidgetHostImpl.
  2. It calls drag_security_info_.OnDragInitiated, which unconditionally overwrites the cached site_instance_group_id_ with the attacker’s ID, completely poisoning the security state.
  3. It attempts to call native_view->StartDragAndDrop() a second time. Because the OS already has an active drag, this returns false.

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::DragTargetDrop calls GrantFileAccessFromDropData. Because the drop was erroneously validated, the browser explicitly grants the attacker’s renderer process read access to the local file via ChildProcessSecurityPolicyImpl::GrantReadFile.
  • Denial of Service: Overwriting current_source_rwh_for_drag_ prevents the victim frame from receiving the DragSourceEndedAt event, 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.)

  1. Navigate to https://victim.com, which embeds a cross-site iframe from https://attacker.com.
  2. Assume the attacker.com renderer process is compromised and can send arbitrary Mojo IPCs.
  3. The user starts a physical drag operation on a sensitive element in the victim.com main frame.
  4. The browser process begins the drag and caches the SiteInstanceGroup ID for victim.com.
  5. The compromised attacker.com renderer immediately sends a blink::mojom::LocalFrameHost::StartDragging IPC to the browser.
  6. 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.
  7. The user drops the item onto the attacker.com iframe.
  8. The browser’s IsValidDragTarget check passes because the state now matches the attacker’s ID.
  9. The attacker.com renderer receives the victim’s drag data and any associated file access grants.

Suggested Fix

  1. Add Active Drag Checks: In WebContentsViewAndroid::StartDragging (and potentially other platform implementations), check if a drag is already active before processing a new StartDragging request. If an OS drag is in progress, reject the incoming IPC or ignore it.
  2. Robust Cleanup: Ensure that if native_view->StartDragAndDrop() fails, the resulting cleanup (e.g., OnSystemDragEnded) properly resets drag_security_info_ by calling drag_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.

View on issue tracker