Medium chrome Memory Corruption 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactMemory corruption in Navigation
DescriptionMemory corruption in Navigation
ComponentNavigation
Sub-componentiOS
Bug ClassMemory Corruption
Tracker429432679
Fix commit1efe836112ba (chromium/src) +156/-6
CISA KEVNot listed
Credited@RenwaX23
Disclosed2026-10-20

Changed Functions

FunctionChangeNotes
if
ios/web/web_state/ui/crw_web_controller.mm
modified

Files Changed

  • ios/testing/http_server_bundle_data.filelist
  • ios/chrome/browser/web/model/BUILD.gn
  • ios/chrome/browser/web/model/web_drag_drop_egtest.mm
  • ios/testing/data/http_server_files/javascript_link.html
  • ios/web/web_state/ui/crw_web_controller.mm
  • ios/testing/data/http_server_files/iframe_drag_link.html
  • ios/testing/data/http_server_files/link.html
From 1efe836112ba7e7018f0b5a83eac05883f4d494c Mon Sep 17 00:00:00 2001
From: Mike Dougherty <[email protected]>
Date: Fri, 18 Sep 2026 14:09:26 -0700
Subject: [PATCH] [iOS] Update logic to open drag and dropped URLs in a new tab

Previously, URLs dropped onto a tab would open within that tab. This CL
updates the logic to match Chrome on other platforms where dropped URLs
now open a new tab.

Additionally, add `aria-label` to link in link.html in order to support
the existing `LongPressLinkAndDragToView` helper and add a new
`javascript_link.html` file to support testing of a javascript link.

Fixed: 429432679
Change-Id: I14fc46dea73859dbfe733b275ceceb2e11c711bc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8425547
Reviewed-by: Gauthier Ambard <[email protected]>
Commit-Queue: Mike Dougherty <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1701076}
---
diff --git a/ios/chrome/browser/web/model/web_drag_drop_egtest.mm b/ios/chrome/browser/web/model/web_drag_drop_egtest.mm
new file mode 100644
index 0000000..0e93ab97
--- /dev/null
+++ b/ios/chrome/browser/web/model/web_drag_drop_egtest.mm
@@ -0,0 +1,106 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
+#import "ios/chrome/test/earl_grey/chrome_test_case.h"
+#import "ios/chrome/test/earl_grey/chrome_xcui_actions.h"
+#import "ios/testing/earl_grey/earl_grey_test.h"
+#import "net/test/embedded_test_server/embedded_test_server.h"
+#import "url/gurl.h"
+
+namespace {
+
+// Initiates a drag on the `link` element and drops it to the lower right of the
+// web view.
+bool LongPressLinkAndDragDropToWebView() {
+  // Offset for dropping items onto the web view to avoid ending the drag within
+  // the context menu bounds.
+  CGVector kLowerRightWindowOffset = {0.85, 0.85};
+  return chrome_test_util::LongPressLinkAndDragToView(
+      @"link", /*src_window_number=*/0, /*dst_accessibility_identifier=*/nil,
+      /*dst_window_number=*/0, kLowerRightWindowOffset);
+}
+
+}  // namespace
+
+// Test case for drag and drop interactions in web content.
+@interface WebDragDropTestCase : ChromeTestCase
+@end
+
+@implementation WebDragDropTestCase
+
+- (void)setUp {
+  [super setUp];
+  GREYAssertTrue(self.testServer->Start(), @"Server did not start.");
+}
+
+// Tests that dragging and dropping a web link opens the URL in a new tab.
+- (void)testDragAndDropLink {
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/link.html")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Link"];
+
+  GREYAssert(LongPressLinkAndDragDropToWebView(),
+             @"Failed to drag link to view");
+
+  [ChromeEarlGrey waitForMainTabCount:2];
+  const GURL expectedURL = self.testServer->GetURL("/pony.html");
+  [ChromeEarlGrey waitForWebStateVisibleURL:expectedURL];
+  [ChromeEarlGrey
+      waitForWebStateContainingText:"Anyone know any good pony jokes?"];
+}
+
+// Tests that dragging and dropping a web link in an incognito tab opens the URL
+// in a new incognito tab.
+- (void)testDragAndDropLinkInIncognito {
+  [ChromeEarlGrey openNewIncognitoTab];
+  [ChromeEarlGrey closeAllNormalTabs];
+
+  [ChromeEarlGrey waitForIncognitoTabCount:1];
+  [ChromeEarlGrey waitForMainTabCount:0];
+
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/link.html")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Link"];
+
+  GREYAssert(LongPressLinkAndDragDropToWebView(),
+             @"Failed to drag link to view");
+
+  [ChromeEarlGrey waitForIncognitoTabCount:2];
+  [ChromeEarlGrey waitForMainTabCount:0];
+  const GURL expectedURL = self.testServer->GetURL("/pony.html");
+  [ChromeEarlGrey waitForWebStateVisibleURL:expectedURL];
+  [ChromeEarlGrey
+      waitForWebStateContainingText:"Anyone know any good pony jokes?"];
+}
+
+// Tests that dragging and dropping a link with a disallowed scheme (e.g.
+// javascript:) does not open a new tab or navigate.
+- (void)testDragAndDropDisallowedSchemeDoesNotNavigate {
+  const GURL initialURL = self.testServer->GetURL("/javascript_link.html");
+  [ChromeEarlGrey loadURL:initialURL];
+  [ChromeEarlGrey waitForWebStateContainingText:"Link"];
+
+  GREYAssert(LongPressLinkAndDragDropToWebView(),
+             @"Failed to drag link to view");
+
+  [ChromeEarlGrey waitForMainTabCount:1];
+  [ChromeEarlGrey waitForWebStateVisibleURL:initialURL];
+}
+
+// Tests that dragging and dropping a link embedded in an iframe opens the URL
+// in a new tab.
+- (void)testDragAndDropLinkFromIframe {
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/iframe_drag_link.html")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Iframe Loaded"];
+
+  GREYAssert(LongPressLinkAndDragDropToWebView(),
+             @"Failed to drag link to view");
+
+  [ChromeEarlGrey waitForMainTabCount:2];
+  const GURL expectedURL = self.testServer->GetURL("/pony.html");
+  [ChromeEarlGrey waitForWebStateVisibleURL:expectedURL];
+  [ChromeEarlGrey
+      waitForWebStateContainingText:"Anyone know any good pony jokes?"];
+}
+
+@end
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 9505481..7e0009d 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -52,9 +52,11 @@
 #import "ios/web/public/content_type_util.h"
 #import "ios/web/public/find_in_page/crw_find_interaction.h"
 #import "ios/web/public/js_messaging/web_frames_manager.h"
+#import "ios/web/public/navigation/referrer.h"
 #import "ios/web/public/permissions/permissions.h"
 #import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/public/web_client.h"
+#import "ios/web/public/web_state.h"
 #import "ios/web/security/crw_cert_verification_controller.h"
 #import "ios/web/security/crw_ssl_status_updater.h"
 #import "ios/web/util/wk_web_view_util.h"
@@ -74,6 +76,7 @@
 #import "ios/web/web_state/web_view_pass_key.h"
 #import "net/base/apple/url_conversions.h"
 #import "services/metrics/public/cpp/ukm_builders.h"
+#import "ui/base/window_open_disposition.h"
 #import "url/gurl.h"
 #import "url/origin.h"
 
@@ -2028,12 +2031,18 @@
 }
 
 - (void)loadUrlObjectsCompletion:(NSArray<NSURL*>*)objects {
-  GURL URL = net::GURLWithNSURL([objects firstObject]);
-  if (!_isBeingDestroyed && URL.is_valid() && URL.SchemeIsHTTPOrHTTPS()) {
-    web::NavigationManager::WebLoadParams params(URL);
-    params.transition_type = ui::PAGE_TRANSITION_TYPED;
-    self.webStateImpl->GetNavigationManager()->LoadURLWithParams(params);
+  if (_isBeingDestroyed || !self.webStateImpl) {
+    return;
   }
+  GURL URL = net::GURLWithNSURL([objects firstObject]);
+  if (!URL.is_valid() || !URL.SchemeIsHTTPOrHTTPS()) {
+    return;
+  }
+  web::WebState::OpenURLParams params(URL, web::Referrer(),
+                                      WindowOpenDisposition::NEW_FOREGROUND_TAB,
+                                      ui::PAGE_TRANSITION_LINK,
+                                      /*is_renderer_initiated=*/false);
+  self.webStateImpl->OpenURL(params);
 }
 
 #pragma mark - Testing-Only Methods
diff --git a/ios/testing/data/http_server_files/iframe_drag_link.html b/ios/testing/data/http_server_files/iframe_drag_link.html
new file mode 100644
index 0000000..75eb748
--- /dev/null
+++ b/ios/testing/data/http_server_files/iframe_drag_link.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!--
+Copyright 2026 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<html>
+  <head>
+    <title>Iframe Drag Link</title>
+  </head>
+  <body>
+    <iframe src="link.html" style="width:200px;height:200px;border:none;" onload="document.body.appendChild(document.createTextNode('Iframe Loaded'));"></iframe>
+  </body>
+</html>
diff --git a/ios/testing/data/http_server_files/javascript_link.html b/ios/testing/data/http_server_files/javascript_link.html
new file mode 100644
index 0000000..bdbb83a
--- /dev/null
+++ b/ios/testing/data/http_server_files/javascript_link.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+
+<!--
+Copyright 2026 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+This file contains a link with a javascript: URL scheme. The link is at a
+precise position to be able to tap it.
+-->
+
+<html>
+  <body>
+    <a href="javascript:void(0);" id="link" aria-label="link" style="display:inline-block;position:absolute;left:40px;top:40px;width:10px;height:10px;">Link</a>
+  </body>
+</html>
diff --git a/ios/testing/data/http_server_files/link.html b/ios/testing/data/http_server_files/link.html
index 6c5b0f7..8bfbbee 100644
--- a/ios/testing/data/http_server_files/link.html
+++ b/ios/testing/data/http_server_files/link.html
@@ -13,6 +13,6 @@
 
 <html>
   <body>
-    <a href="pony.html" id="link" style="display:inline-block;position:absolute;left:40px;top:40px;width:10px;height:10px;">Link</a>
+    <a href="pony.html" id="link" aria-label="link" style="display:inline-block;position:absolute;left:40px;top:40px;width:10px;height:10px;">Link</a>
   </body>
 </html>
diff --git a/ios/testing/http_server_bundle_data.filelist b/ios/testing/http_server_bundle_data.filelist
index 3f6c0aa..85ece72 100644
--- a/ios/testing/http_server_bundle_data.filelist
+++ b/ios/testing/http_server_bundle_data.filelist
@@ -37,9 +37,11 @@
 data/http_server_files/history.js
 data/http_server_files/history_go.html
 data/http_server_files/history_go.js
+data/http_server_files/iframe_drag_link.html
 data/http_server_files/iframe_form.html
 data/http_server_files/iframe_host.html
 data/http_server_files/insecure_form.html
+data/http_server_files/javascript_link.html
 data/http_server_files/link.html
 data/http_server_files/links.html
 data/http_server_files/memory_usage.html
diff --git a/ios/chrome/browser/web/model/BUILD.gn b/ios/chrome/browser/web/model/BUILD.gn
index e5ad106..9b5ee2f 100644
--- a/ios/chrome/browser/web/model/BUILD.gn
+++ b/ios/chrome/browser/web/model/BUILD.gn
@@ -519,6 +519,7 @@
     "stop_loading_egtest.mm",
     "tab_order_egtest.mm",
     "visible_url_egtest.mm",
+    "web_drag_drop_egtest.mm",
     "web_share_egtest.mm",
     "window_open_by_dom_egtest.mm",
   ]
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/ios/testing/data/http_server_files/iframe_drag_link.html b/ios/testing/data/http_server_files/iframe_drag_link.html
new file mode 100644
index 0000000..75eb748
--- /dev/null
+++ b/ios/testing/data/http_server_files/iframe_drag_link.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!--
+Copyright 2026 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<html>
+  <head>
+    <title>Iframe Drag Link</title>
+  </head>
+  <body>
+    <iframe src="link.html" style="width:200px;height:200px;border:none;" onload="document.body.appendChild(document.createTextNode('Iframe Loaded'));"></iframe>
+  </body>
+</html>
diff --git a/ios/testing/data/http_server_files/javascript_link.html b/ios/testing/data/http_server_files/javascript_link.html
new file mode 100644
index 0000000..bdbb83a
--- /dev/null
+++ b/ios/testing/data/http_server_files/javascript_link.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+
+<!--
+Copyright 2026 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+This file contains a link with a javascript: URL scheme. The link is at a
+precise position to be able to tap it.
+-->
+
+<html>
+  <body>
+    <a href="javascript:void(0);" id="link" aria-label="link" style="display:inline-block;position:absolute;left:40px;top:40px;width:10px;height:10px;">Link</a>
+  </body>
+</html>
diff --git a/ios/testing/data/http_server_files/link.html b/ios/testing/data/http_server_files/link.html
index 6c5b0f7..8bfbbee 100644
--- a/ios/testing/data/http_server_files/link.html
+++ b/ios/testing/data/http_server_files/link.html
@@ -13,6 +13,6 @@
 
 <html>
   <body>
-    <a href="pony.html" id="link" style="display:inline-block;position:absolute;left:40px;top:40px;width:10px;height:10px;">Link</a>
+    <a href="pony.html" id="link" aria-label="link" style="display:inline-block;position:absolute;left:40px;top:40px;width:10px;height:10px;">Link</a>
   </body>
 </html>
diff --git a/ios/testing/http_server_bundle_data.filelist b/ios/testing/http_server_bundle_data.filelist
index 3f6c0aa..85ece72 100644
--- a/ios/testing/http_server_bundle_data.filelist
+++ b/ios/testing/http_server_bundle_data.filelist
@@ -37,9 +37,11 @@
 data/http_server_files/history.js
 data/http_server_files/history_go.html
 data/http_server_files/history_go.js
+data/http_server_files/iframe_drag_link.html
 data/http_server_files/iframe_form.html
 data/http_server_files/iframe_host.html
 data/http_server_files/insecure_form.html
+data/http_server_files/javascript_link.html
 data/http_server_files/link.html
 data/http_server_files/links.html
 data/http_server_files/memory_usage.html
Loading diff…

Original Bug Report

reported by [email protected]

Chrome iOS Address Bar Spoof Using Cross-Origin <iframe> and Drag-Drop to a Never Loading Destination


Report description

Chrome iOS Address Bar Spoof Using Cross-Origin <iframe> and Drag-Drop to a Never Loading Destination


Bug location

Where do you want to report your vulnerability?

Chrome VRP – Report security issues affecting the Chrome browser. See program rules


The problem

Please describe the technical details of the vulnerability

If we have a location that will never load like (https://google.com:81) the browser will try to request to the site and won’t change the address bar unless we receive a response, but Chrome has a feature that allows us to redirect to location when tap and holding a link and dropping it inside the current tab. This feature when abused we can change the address bar value to the invalid address ((https://google.com:81) and with our controlled content still on the current origin. There is also another problem which is when we tap and hold a link it will display the context menu to preview the link or options to open in a new tab, but if we embed the link inside a cross-origin iframe the context menu won’t be shown and we can easily drag and drop a link into anywhere.

  • POC: https://rx23.io/poc/chrome/1.html
  • Tap and hold the link and drop it anywhere inside the page
  • Address bar changed to https://accounts.google.com:81/ with our controlled content

My POC code explanation:

  • Cross origin iframe (I’m using data: URI) with a link pointing to (https://google.com:81)
  • If touchstart on the link we send a postMessage to parent domain
  • Inside parent domain we have a location for dropping which it’s not necessary but just for UI
  • We have a message event listener when we receive the message after couple seconds we change page contents to a fake login

POC Video also attached

Instead of an invalid port a very slow page also can be used, the link also can be customized with displaying an image or any other tricks to spoof the user.

Impact analysis – Please briefly explain who can exploit the vulnerability, and what they gain when doing so

Address bar spoof to trick users into stealing credentials and other data


The cause

What version of Chrome have you found the security issue in?

138.0.7204.119 Stable iOS

No, it is not related to a crash.

Choose the type of vulnerability

Security UI Spoofing

How would you like to be publicly acknowledged for your report?

@RenwaX23

View on issue tracker