Low chrome Memory Corruption 🔧 Commit mapped

Overview

Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactMemory corruption in BrowserTag
DescriptionMemory corruption in BrowserTag
ComponentBrowserTag
Bug ClassMemory Corruption
Tracker553334273
Fix commit8d17e06dbdfe (chromium/src) +62/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-10-20

Changed Functions

FunctionChangeNotes
for
chrome/test/data/webui/webview/webui_webview_browsertest.cc
modified
suite
chrome/test/data/webui/webview/webview_untrusted_test.ts
modified

Files Changed

  • extensions/browser/guest_view/web_view/web_view_permission_helper.cc
  • chrome/test/data/webui/webview/webview_untrusted_test.ts
  • chrome/test/data/webui/webview/webui_webview_browsertest.cc
From 8d17e06dbdfe0a7c0e8042a78ee0328c1f55cc46 Mon Sep 17 00:00:00 2001
From: Kevin McNee <[email protected]>
Date: Tue, 22 Sep 2026 15:17:50 -0700
Subject: [PATCH] Prevent chrome-untrusted from approving webview permissions

Similar to https://crbug.com/502179319 if a webview has a
chrome-untrusted page as an embedder, it should not be trusted to grant
permissions.

Fixed: 553334273
Change-Id: Ic1461da87e31c75786c8742a45e45bf07079e4ac
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8431428
Reviewed-by: Alex Moshchuk <[email protected]>
Auto-Submit: Kevin McNee <[email protected]>
Commit-Queue: Kevin McNee <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1702992}
---
diff --git a/extensions/browser/guest_view/web_view/web_view_permission_helper.cc b/extensions/browser/guest_view/web_view/web_view_permission_helper.cc
index 693c97f..d3bfc80e 100644
--- a/extensions/browser/guest_view/web_view/web_view_permission_helper.cc
+++ b/extensions/browser/guest_view/web_view/web_view_permission_helper.cc
@@ -440,6 +440,19 @@
     return;
   }
 
+  // A chrome-untrusted embedder can't be trusted to approve permissions.
+  // New Window and Dialog are excluded, since they reuse this path but aren't
+  // really permissions.
+  if (permission_type != WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW &&
+      permission_type != WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG &&
+      web_view_guest_->GetOwnerSiteURL().SchemeIs(
+          content::kChromeUIUntrustedScheme)) {
+    base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(callback), allowed_by_default, std::string()));
+    return;
+  }
+
   int request_id = next_permission_request_id_++;
   pending_permission_requests_[request_id] = PermissionResponseInfo(
       std::move(callback), permission_type, allowed_by_default);
diff --git a/chrome/test/data/webui/webview/webui_webview_browsertest.cc b/chrome/test/data/webui/webview/webui_webview_browsertest.cc
index c128fd95..0993a424 100644
--- a/chrome/test/data/webui/webview/webui_webview_browsertest.cc
+++ b/chrome/test/data/webui/webview/webui_webview_browsertest.cc
@@ -30,10 +30,12 @@
 #include "chrome/test/base/test_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chrome/test/base/web_ui_mocha_browser_test.h"
+#include "components/download/public/common/download_item.h"
 #include "components/prefs/pref_service.h"
 #include "components/webui/chrome_urls/pref_names.h"
 #include "content/public/browser/back_forward_cache.h"
 #include "content/public/browser/context_menu_params.h"
+#include "content/public/browser/download_manager.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/web_contents.h"
@@ -551,6 +553,10 @@
     WebUIMochaBrowserTest::SetUpOnMainThread();
   }
 
+  GURL GetTestUrl(const std::string& path) const {
+    return embedded_test_server()->base_url().Resolve(path);
+  }
+
   content::WebContents* GetWebContentsForTesting() {
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
@@ -568,4 +574,25 @@
                                    true));
 }
 
+IN_PROC_BROWSER_TEST_F(UntrustedWebUIWebViewBrowserTest,
+                       PermissionRequestAutoDeny) {
+  EXPECT_TRUE(RunTestOnWebContents(
+      GetWebContentsForTesting(), "webview/webview_untrusted_test.js",
+      base::StringPrintf("window.downloadUrl = '%s'; "
+                         "runMochaTest('WebviewUntrustedBasicTest', "
+                         "'PermissionRequestAutoDenyInUntrusted');",
+                         GetTestUrl("download-test3.gif").spec().c_str()),
+      true));
+
+  content::DownloadManager::DownloadVector downloads;
+  browser()->GetProfile()->GetDownloadManager()->GetAllDownloads(&downloads);
+  EXPECT_TRUE(downloads.empty());
+  // If the test fails and a download was started, cancel it so that an
+  // in-progress download prompt does not block browser shutdown during test
+  // teardown.
+  for (download::DownloadItem* download : downloads) {
+    download->Cancel(false);
+  }
+}
+
 #endif  // !BUILDFLAG(IS_MAC)
diff --git a/chrome/test/data/webui/webview/webview_untrusted_test.ts b/chrome/test/data/webui/webview/webview_untrusted_test.ts
index 2c504f66..2ce33ef 100644
--- a/chrome/test/data/webui/webview/webview_untrusted_test.ts
+++ b/chrome/test/data/webui/webview/webview_untrusted_test.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {assertThrows} from 'chrome-untrusted://webui-test/chai_assert.js';
+import {assertFalse, assertThrows} from 'chrome-untrusted://webui-test/chai_assert.js';
 
 suite('WebviewUntrustedBasicTest', function() {
   function createWebview(): chrome.webviewTag.WebView {
@@ -12,6 +12,10 @@
     return webview;
   }
 
+  function getDownloadUrl(): string {
+    return (window as unknown as Window & {downloadUrl: string}).downloadUrl;
+  }
+
   test('BannedApisThrowInUntrusted', async () => {
     const webview = createWebview();
     await new Promise(resolve => {
@@ -37,4 +41,21 @@
       webview.loadDataWithBaseUrl('data:text/html,test', 'https://example.com');
     });
   });
+
+  test('PermissionRequestAutoDenyInUntrusted', async () => {
+    const webview = createWebview();
+    let receivedPermissionRequest = false;
+    webview.addEventListener('permissionrequest', event => {
+      receivedPermissionRequest = true;
+      const e = event as chrome.webviewTag.PermissionRequestEvent;
+      e.request.allow();
+    });
+
+    await new Promise(resolve => {
+      webview.src = getDownloadUrl();
+      webview.addEventListener('loadstop', resolve);
+    });
+
+    assertFalse(receivedPermissionRequest);
+  });
 });
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/chrome/test/data/webui/webview/webui_webview_browsertest.cc b/chrome/test/data/webui/webview/webui_webview_browsertest.cc
index c128fd95..0993a424 100644
--- a/chrome/test/data/webui/webview/webui_webview_browsertest.cc
+++ b/chrome/test/data/webui/webview/webui_webview_browsertest.cc
@@ -30,10 +30,12 @@
 #include "chrome/test/base/test_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chrome/test/base/web_ui_mocha_browser_test.h"
+#include "components/download/public/common/download_item.h"
 #include "components/prefs/pref_service.h"
 #include "components/webui/chrome_urls/pref_names.h"
 #include "content/public/browser/back_forward_cache.h"
 #include "content/public/browser/context_menu_params.h"
+#include "content/public/browser/download_manager.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/web_contents.h"
@@ -551,6 +553,10 @@
     WebUIMochaBrowserTest::SetUpOnMainThread();
   }
 
+  GURL GetTestUrl(const std::string& path) const {
+    return embedded_test_server()->base_url().Resolve(path);
+  }
+
   content::WebContents* GetWebContentsForTesting() {
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
@@ -568,4 +574,25 @@
                                    true));
 }
 
+IN_PROC_BROWSER_TEST_F(UntrustedWebUIWebViewBrowserTest,
+                       PermissionRequestAutoDeny) {
+  EXPECT_TRUE(RunTestOnWebContents(
+      GetWebContentsForTesting(), "webview/webview_untrusted_test.js",
+      base::StringPrintf("window.downloadUrl = '%s'; "
+                         "runMochaTest('WebviewUntrustedBasicTest', "
+                         "'PermissionRequestAutoDenyInUntrusted');",
+                         GetTestUrl("download-test3.gif").spec().c_str()),
+      true));
+
+  content::DownloadManager::DownloadVector downloads;
+  browser()->GetProfile()->GetDownloadManager()->GetAllDownloads(&downloads);
+  EXPECT_TRUE(downloads.empty());
+  // If the test fails and a download was started, cancel it so that an
+  // in-progress download prompt does not block browser shutdown during test
+  // teardown.
+  for (download::DownloadItem* download : downloads) {
+    download->Cancel(false);
+  }
+}
+
 #endif  // !BUILDFLAG(IS_MAC)
diff --git a/chrome/test/data/webui/webview/webview_untrusted_test.ts b/chrome/test/data/webui/webview/webview_untrusted_test.ts
index 2c504f66..2ce33ef 100644
--- a/chrome/test/data/webui/webview/webview_untrusted_test.ts
+++ b/chrome/test/data/webui/webview/webview_untrusted_test.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {assertThrows} from 'chrome-untrusted://webui-test/chai_assert.js';
+import {assertFalse, assertThrows} from 'chrome-untrusted://webui-test/chai_assert.js';
 
 suite('WebviewUntrustedBasicTest', function() {
   function createWebview(): chrome.webviewTag.WebView {
@@ -12,6 +12,10 @@
     return webview;
   }
 
+  function getDownloadUrl(): string {
+    return (window as unknown as Window & {downloadUrl: string}).downloadUrl;
+  }
+
   test('BannedApisThrowInUntrusted', async () => {
     const webview = createWebview();
     await new Promise(resolve => {
@@ -37,4 +41,21 @@
       webview.loadDataWithBaseUrl('data:text/html,test', 'https://example.com');
     });
   });
+
+  test('PermissionRequestAutoDenyInUntrusted', async () => {
+    const webview = createWebview();
+    let receivedPermissionRequest = false;
+    webview.addEventListener('permissionrequest', event => {
+      receivedPermissionRequest = true;
+      const e = event as chrome.webviewTag.PermissionRequestEvent;
+      e.request.allow();
+    });
+
+    await new Promise(resolve => {
+      webview.src = getDownloadUrl();
+      webview.addEventListener('loadstop', resolve);
+    });
+
+    assertFalse(receivedPermissionRequest);
+  });
 });
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.