Low chrome UAF 🔧 Commit mapped

Overview

Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in PDF
DescriptionUse after free in PDF
ComponentPDF
Sub-componentPDF
Bug ClassUAF
Tracker40056239
Fix commit0520a5aa3f76 (chromium/src) +25/-17
CISA KEVNot listed
Creditedkirtikumarar
Disclosed2026-10-20

Changed Functions

FunctionChangeNotes
if
chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
modified
IN_PROC_BROWSER_TEST_P
chrome/browser/pdf/pdf_extension_test.cc
modified

Files Changed

  • chrome/browser/pdf/pdf_extension_test.cc
  • chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
From 0520a5aa3f76496749fca4c1f55d9cedb12f6517 Mon Sep 17 00:00:00 2001
From: Lei Zhang <[email protected]>
Date: Wed, 16 Sep 2026 17:02:31 -0700
Subject: [PATCH] [PDF] Do not load PDF Viewer for HTTP(S) text/plain responses

When a web server serves a PDF containing binary bytes in the first 1024
bytes with a "text/plain" Content-Type header, net::SniffMimeType()
sniffs the response MIME type as "application/pdf". Before this CL,
PluginResponseInterceptorURLLoaderThrottle intercepted the navigation
and launched the PDF Viewer, only for the PDF Viewer to reject the
"text/plain" Content-Type header and show a load error.

Fix this by checking the original HTTP(S) Content-Type header in
PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse() when
`response_head->mime_type` is "application/pdf". If the original header
MIME type is "text/plain", revert `response_head->mime_type` back to it
so the PDF Viewer does not launch and the content renders inline as
plain text.

Update PDFExtensionTest.BinaryPdfServedAsTextPlain to reflect this new
behavior.

TAG=agy
CONV=ee25eb48-0a12-4307-a005-1b2de4305209

Bug: 40056239
Change-Id: Iee8490e34ca9bb19b273ccb3539e2b34ba7c7b16
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8419586
Commit-Queue: Lei Zhang <[email protected]>
Reviewed-by: Andy Phan <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1699353}
---
diff --git a/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc b/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
index 529410b..6e8f30c 100644
--- a/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
+++ b/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
@@ -155,16 +155,27 @@
   }
 
 #if BUILDFLAG(ENABLE_PDF)
-  // text/pdf is an alias for application/pdf for the purpose of invoking the
-  // built-in PDF viewer (crbug.com/40774340). Canonicalize it here -- before
-  // the download decision below -- so the download pref, the PDF viewer
-  // machinery, and the committed WebContents contents MIME type uniformly
-  // observe application/pdf, preserving the invariant that a full-page PDF's
-  // contents MIME type is application/pdf.
   if (response_head->mime_type == "text/pdf") {
+    // text/pdf is an alias for application/pdf for the purpose of invoking the
+    // built-in PDF viewer (crbug.com/40774340). Canonicalize it here -- before
+    // the download decision below -- so the download pref, the PDF viewer
+    // machinery, and the committed WebContents contents MIME type uniformly
+    // observe application/pdf, preserving the invariant that a full-page PDF's
+    // contents MIME type is application/pdf.
     response_head->mime_type = pdf::kPDFMimeType;
+  } else if (response_head->mime_type == pdf::kPDFMimeType &&
+             response_url.SchemeIsHTTPOrHTTPS() && response_head->headers) {
+    // If net::SniffMimeType() sniffed an HTTP(S) "text/plain" response as
+    // "application/pdf", revert `response_head->mime_type` back to
+    // "text/plain". The PDF viewer rejects HTTP(S) responses with a
+    // "text/plain" Content-Type header, so do not intercept the response.
+    std::string original_header_mime_type;
+    if (response_head->headers->GetMimeType(&original_header_mime_type) &&
+        original_header_mime_type == "text/plain") {
+      response_head->mime_type = original_header_mime_type;
+    }
   }
-#endif
+#endif  // BUILDFLAG(ENABLE_PDF)
 
   if (content::download_utils::MustDownload(
           web_contents->GetBrowserContext(), response_url,
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index f3780bc..c99b6f0b 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -1052,17 +1052,14 @@
 }
 
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, BinaryPdfServedAsTextPlain) {
-  // When a PDF contains binary bytes in the first 1024 bytes,
-  // net::SniffMimeType() sniffs "text/plain" for binary content and matches the
-  // "%PDF-" magic number, overriding the MIME type to "application/pdf" and
-  // loading the PDF Viewer. However, DocumentLoaderImpl::Init() rejects HTTP
-  // responses with a "text/plain" Content-Type header, so loading the PDF
-  // document fails.
-  // TODO(crbug.com/40056239): Render as plain text instead?
+  // Even when a PDF contains binary bytes in the first 1024 bytes, causing
+  // net::SniffMimeType() to match the "%PDF-" magic number, the PDF Viewer does
+  // not load for HTTP responses with a "text/plain" Content-Type header and the
+  // content is rendered as plain text.
   const GURL url = embedded_test_server()->GetURL("/text_plain/pdf/test.pdf");
-  EXPECT_FALSE(LoadPdf(url));
-  EXPECT_EQ(pdf::kPDFMimeType, GetActiveWebContents()->GetContentsMimeType());
-  EXPECT_EQ(1, CountPDFProcesses());
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+  EXPECT_EQ("text/plain", GetActiveWebContents()->GetContentsMimeType());
+  EXPECT_EQ(0, CountPDFProcesses());
 }
 
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, MostlyTextPdfServedAsTextPlain) {
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index f3780bc..c99b6f0b 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -1052,17 +1052,14 @@
 }
 
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, BinaryPdfServedAsTextPlain) {
-  // When a PDF contains binary bytes in the first 1024 bytes,
-  // net::SniffMimeType() sniffs "text/plain" for binary content and matches the
-  // "%PDF-" magic number, overriding the MIME type to "application/pdf" and
-  // loading the PDF Viewer. However, DocumentLoaderImpl::Init() rejects HTTP
-  // responses with a "text/plain" Content-Type header, so loading the PDF
-  // document fails.
-  // TODO(crbug.com/40056239): Render as plain text instead?
+  // Even when a PDF contains binary bytes in the first 1024 bytes, causing
+  // net::SniffMimeType() to match the "%PDF-" magic number, the PDF Viewer does
+  // not load for HTTP responses with a "text/plain" Content-Type header and the
+  // content is rendered as plain text.
   const GURL url = embedded_test_server()->GetURL("/text_plain/pdf/test.pdf");
-  EXPECT_FALSE(LoadPdf(url));
-  EXPECT_EQ(pdf::kPDFMimeType, GetActiveWebContents()->GetContentsMimeType());
-  EXPECT_EQ(1, CountPDFProcesses());
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+  EXPECT_EQ("text/plain", GetActiveWebContents()->GetContentsMimeType());
+  EXPECT_EQ(0, CountPDFProcesses());
 }
 
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, MostlyTextPdfServedAsTextPlain) {
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.