Low CVSS 4.3 chrome Policy Bypass 🔧 Commit mapped

Overview

Low
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactPolicy bypass in MHTML
DescriptionPolicy bypass in MHTML
ComponentMHTML
Bug ClassPolicy Bypass
Tracker517383492
Fix commit7071428f8304 (chromium/src) +65/-0
CWECWE-346 (Origin validation error)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-05-28 (per vendor advisory)
Fix landed2026-06-03 (public git)
Disclosed2026-07-29
Patch gap56 days — fix public in source before the advisory

Changed Functions

FunctionChangeNotes
NavigationMhtmlImprovementsBrowserTest
content/browser/navigation_mhtml_browsertest.cc
modified
NavigationMhtmlImprovementsBrowserTest
content/browser/navigation_mhtml_browsertest.cc
modified

Files Changed

  • content/browser/navigation_mhtml_browsertest.cc
  • content/browser/renderer_host/render_frame_host_impl.cc
From 7071428f8304742aea0b30bf583583cceb104476 Mon Sep 17 00:00:00 2001
From: Patrick Meenan <[email protected]>
Date: Wed, 03 Jun 2026 06:33:08 -0700
Subject: [PATCH] Block WebSocket and WebTransport connections in MHTML documents

MHTML documents are intended to be strictly sandboxed and isolated from
the network. However, WebSockets and WebTransport both connect directly
to the browser process via Mojo, bypassing the renderer-side resource
fetcher network isolation.

This CL adds browser-side verification to CreateWebSocketConnector and
CreateWebTransportConnector in RenderFrameHostImpl. Requests originating
from MHTML documents now correctly trigger a bad Mojo message and
terminate the requesting renderer process.

Added regression integration tests to verify WebSocket and WebTransport
bindings are successfully blocked and terminated.

Bug: 517383492
Change-Id: I1a9ca360f381566f6445baeba6e9a8c8eda2eab4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7891435
Reviewed-by: Arthur Sonzogni <[email protected]>
Commit-Queue: Patrick Meenan <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1640884}
---

diff --git a/content/browser/navigation_mhtml_browsertest.cc b/content/browser/navigation_mhtml_browsertest.cc
index 682db42..df1989b 100644
--- a/content/browser/navigation_mhtml_browsertest.cc
+++ b/content/browser/navigation_mhtml_browsertest.cc
@@ -965,4 +965,61 @@
   EXPECT_EQ(1, num_documents);
 }
 
+// Helper test fixture to enable `kMHTML_Improvements`. Enabling this feature
+// allows script execution in MHTML documents, which is necessary for the tests
+// to execute the JavaScript payload that triggers the Mojo IPC request.
+class NavigationMhtmlImprovementsBrowserTest
+    : public NavigationMhtmlBrowserTest {
+ public:
+  NavigationMhtmlImprovementsBrowserTest() {
+    scoped_feature_list_.InitAndEnableFeature(
+        blink::features::kMHTML_Improvements);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(NavigationMhtmlImprovementsBrowserTest,
+                       MhtmlBlocksWebSocket) {
+  MhtmlArchive mhtml_archive;
+  mhtml_archive.AddHtmlDocument(GURL("http://example.com"), "MHTML content");
+  GURL mhtml_url = mhtml_archive.Write("index.mhtml");
+  EXPECT_TRUE(NavigateToURL(shell(), mhtml_url));
+
+  RenderFrameHostImpl* main_document = main_frame_host();
+  EXPECT_TRUE(main_document->is_mhtml_document());
+
+  RenderProcessHostBadMojoMessageWaiter kill_waiter(
+      main_document->GetProcess());
+
+  ExecuteScriptAsync(main_document, "new WebSocket('ws://127.0.0.1');");
+
+  EXPECT_EQ(
+      "Received bad user message: WebSockets are not allowed in MHTML "
+      "documents.",
+      kill_waiter.Wait());
+}
+
+IN_PROC_BROWSER_TEST_F(NavigationMhtmlImprovementsBrowserTest,
+                       MhtmlBlocksWebTransport) {
+  MhtmlArchive mhtml_archive;
+  mhtml_archive.AddHtmlDocument(GURL("http://example.com"), "MHTML content");
+  GURL mhtml_url = mhtml_archive.Write("index.mhtml");
+  EXPECT_TRUE(NavigateToURL(shell(), mhtml_url));
+
+  RenderFrameHostImpl* main_document = main_frame_host();
+  EXPECT_TRUE(main_document->is_mhtml_document());
+
+  RenderProcessHostBadMojoMessageWaiter kill_waiter(
+      main_document->GetProcess());
+
+  ExecuteScriptAsync(main_document, "new WebTransport('https://127.0.0.1');");
+
+  EXPECT_EQ(
+      "Received bad user message: WebTransport is not allowed in MHTML "
+      "documents.",
+      kill_waiter.Wait());
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 7d052f9..e08049d0 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -14758,6 +14758,10 @@
 
 void RenderFrameHostImpl::CreateWebSocketConnector(
     mojo::PendingReceiver<blink::mojom::WebSocketConnector> receiver) {
+  if (is_mhtml_document()) {
+    mojo::ReportBadMessage("WebSockets are not allowed in MHTML documents.");
+    return;
+  }
   mojo::MakeSelfOwnedReceiver(
       std::make_unique<WebSocketConnectorImpl>(
           GlobalRenderFrameHostId(GetProcess()->GetID(), routing_id_),
@@ -14768,6 +14772,10 @@
 
 void RenderFrameHostImpl::CreateWebTransportConnector(
     mojo::PendingReceiver<blink::mojom::WebTransportConnector> receiver) {
+  if (is_mhtml_document()) {
+    mojo::ReportBadMessage("WebTransport is not allowed in MHTML documents.");
+    return;
+  }
   mojo::MakeSelfOwnedReceiver(
       std::make_unique<WebTransportConnectorImpl>(
           GetProcess()->GetDeprecatedID(), weak_ptr_factory_.GetWeakPtr(),
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/content/browser/navigation_mhtml_browsertest.cc b/content/browser/navigation_mhtml_browsertest.cc
index 682db42..df1989b 100644
--- a/content/browser/navigation_mhtml_browsertest.cc
+++ b/content/browser/navigation_mhtml_browsertest.cc
@@ -965,4 +965,61 @@
   EXPECT_EQ(1, num_documents);
 }
 
+// Helper test fixture to enable `kMHTML_Improvements`. Enabling this feature
+// allows script execution in MHTML documents, which is necessary for the tests
+// to execute the JavaScript payload that triggers the Mojo IPC request.
+class NavigationMhtmlImprovementsBrowserTest
+    : public NavigationMhtmlBrowserTest {
+ public:
+  NavigationMhtmlImprovementsBrowserTest() {
+    scoped_feature_list_.InitAndEnableFeature(
+        blink::features::kMHTML_Improvements);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(NavigationMhtmlImprovementsBrowserTest,
+                       MhtmlBlocksWebSocket) {
+  MhtmlArchive mhtml_archive;
+  mhtml_archive.AddHtmlDocument(GURL("http://example.com"), "MHTML content");
+  GURL mhtml_url = mhtml_archive.Write("index.mhtml");
+  EXPECT_TRUE(NavigateToURL(shell(), mhtml_url));
+
+  RenderFrameHostImpl* main_document = main_frame_host();
+  EXPECT_TRUE(main_document->is_mhtml_document());
+
+  RenderProcessHostBadMojoMessageWaiter kill_waiter(
+      main_document->GetProcess());
+
+  ExecuteScriptAsync(main_document, "new WebSocket('ws://127.0.0.1');");
+
+  EXPECT_EQ(
+      "Received bad user message: WebSockets are not allowed in MHTML "
+      "documents.",
+      kill_waiter.Wait());
+}
+
+IN_PROC_BROWSER_TEST_F(NavigationMhtmlImprovementsBrowserTest,
+                       MhtmlBlocksWebTransport) {
+  MhtmlArchive mhtml_archive;
+  mhtml_archive.AddHtmlDocument(GURL("http://example.com"), "MHTML content");
+  GURL mhtml_url = mhtml_archive.Write("index.mhtml");
+  EXPECT_TRUE(NavigateToURL(shell(), mhtml_url));
+
+  RenderFrameHostImpl* main_document = main_frame_host();
+  EXPECT_TRUE(main_document->is_mhtml_document());
+
+  RenderProcessHostBadMojoMessageWaiter kill_waiter(
+      main_document->GetProcess());
+
+  ExecuteScriptAsync(main_document, "new WebTransport('https://127.0.0.1');");
+
+  EXPECT_EQ(
+      "Received bad user message: WebTransport is not allowed in MHTML "
+      "documents.",
+      kill_waiter.Wait());
+}
+
 }  // namespace content
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.