Low chrome Logic Error 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactPolicy bypass in MHTML
DescriptionPolicy bypass in MHTML
ComponentMHTML
Bug ClassLogic Error
Tracker517383492
Fix commit7071428f8304 (chromium/src) +65/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-07-29

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 <pmeenan@chromium.org>
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 <arthursonzogni@chromium.org>
Commit-Queue: Patrick Meenan <pmeenan@chromium.org>
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.