Chrome · PDF
CVE-2026-3932
Logic Error in PDF
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java |
modified | |
ifchrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.java |
modified |
Files Changed
chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.javachrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.javachrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.javachrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtilsUnitTest.java
Patch
From 2265687230f6a3642e766a68d7c3b201ced0bbf6 Mon Sep 17 00:00:00 2001
From: Shu Yang <shuyng@google.com>
Date: Fri, 06 Feb 2026 13:32:39 -0800
Subject: [PATCH] Restrict PDF re-downloads to safe schemes and preserve initiator
Going back to a PDF URL may require a re-download, and this can be
triggered when the current page is not a PDF. Ensure that these
navigations can't elevate their privileges by limiting to HTTP(S)
and preserving information about the initiator.
Bug: 478296121
Change-Id: Ic08a4aa797b0ba11f7010714570e4e9d3be31a48
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7520272
Reviewed-by: Charlie Reis <creis@chromium.org>
Reviewed-by: Sirisha Kavuluru <skavuluru@google.com>
Commit-Queue: Shu Yang <shuyng@google.com>
Cr-Commit-Position: refs/heads/main@{#1581094}
---
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
index ae0b4dee..95f7a504 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -112,6 +112,7 @@
import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.url.GURL;
+import org.chromium.url.Origin;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -1854,8 +1855,15 @@
* @param url The URL that was loaded.
* @param transitionType The transition type to the current URL.
* @param isPdf Whether the navigation is for PDF content.
+ * @param isRendererInitiated Whether the navigation is initiated by renderer.
+ * @param initiatorOrigin The Origin that initiated this navigation.
*/
- void handleDidFinishNavigation(GURL url, int transitionType, boolean isPdf) {
+ void handleDidFinishNavigation(
+ GURL url,
+ int transitionType,
+ boolean isPdf,
+ boolean isRendererInitiated,
+ @Nullable Origin initiatorOrigin) {
mIsNativePageCommitPending = false;
boolean isReload = (transitionType & PageTransition.CORE_MASK) == PageTransition.RELOAD;
// Set isPdf param based on the url. This is because the isPdf param in NavigationHandle is
@@ -1866,11 +1874,20 @@
PdfUtils.shouldOpenPdfInline(isIncognito())
&& PdfUtils.isDownloadedPdf(url.getSpec());
if (!maybeShowNativePage(url.getSpec(), isReload, isPdf ? new PdfInfo() : null)) {
- String downloadUrl = PdfUtils.decodePdfPageUrl(url.getSpec());
+ // This is restricted to HTTP(S) URLs specifically, as these are the only schemes that
+ // necessitate a PDF re-download.
+ String downloadUrl = PdfUtils.getPdfReDownloadUrl(url.getSpec());
if (downloadUrl != null) {
- // When the download url is not null, we are on a pdf native page which requires
- // re-download. Load the download url to trigger the re-download.
- loadUrl(new LoadUrlParams(downloadUrl));
+ // When the download url is not null, we are navigating to a pdf native page which
+ // requires re-download. Load the download url to trigger the re-download.
+ var param = new LoadUrlParams(downloadUrl);
+ // To avoid a SameSite=strict cookie bypass, it is important to preserve whether the
+ // navigation was renderer initiated and what its initiator origin was.
+ param.setIsRendererInitiated(isRendererInitiated);
+ if (initiatorOrigin != null) {
+ param.setInitiatorOrigin(initiatorOrigin);
+ }
+ loadUrl(param);
} else {
showRenderedPage();
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
index eec3439..18b339eb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -318,7 +318,11 @@
mTab.updateTitle();
mTab.handleDidFinishNavigation(
- navigation.getUrl(), navigation.pageTransition(), navigation.isPdf());
+ navigation.getUrl(),
+ navigation.pageTransition(),
+ navigation.isPdf(),
+ navigation.isRendererInitiated(),
+ navigation.getInitiatorOrigin());
mTab.setIsShowingErrorPage(navigation.isErrorPage());
// TODO(crbug.com/40264745) remove this call. onUrlUpdated should have been called
diff --git a/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.java b/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.java
index 61383fa..222a9473 100644
--- a/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.java
+++ b/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.java
@@ -316,6 +316,30 @@
}
/**
+ * Extracts a valid HTTP(S) URL from a PDF page URL for re-downloading.
+ *
+ * <p>This method decodes the provided {@code originalUrl} and verifies that the result uses a
+ * supported scheme (HTTP or HTTPS).
+ *
+ * @param originalUrl The original, potentially encoded, URL string to process.
+ * @return The decoded URL string if it is a valid HTTP(S) URL; {@code null} otherwise.
+ */
+ public static @Nullable String getPdfReDownloadUrl(String originalUrl) {
+ String decodedUrl = decodePdfPageUrl(originalUrl);
+
+ if (decodedUrl == null) {
+ return null;
+ }
+
+ if (decodedUrl.startsWith(UrlConstants.HTTP_URL_PREFIX)
+ || decodedUrl.startsWith(UrlConstants.HTTPS_URL_PREFIX)) {
+ return decodedUrl;
+ }
+
+ return null;
+ }
+
+ /**
* Encode content uri if it is PDF MIME type.
*
* @param uri The uri to be encoded.
diff --git a/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtilsUnitTest.java b/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtilsUnitTest.java
index 91d1c9c..86c1629 100644
--- a/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtilsUnitTest.java
+++ b/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtilsUnitTest.java
@@ -49,6 +49,8 @@
private static final String PDF_BLOB_URL = "blob:https://www.foo.com/abc";
private static final String PDF_LINK_ENCODED =
"chrome-native://pdf/link?url=https%3A%2F%2Fwww.foo.com%2Ftestfiles%2Fpdf%2Fsample.pdf";
+ private static final String PDF_LINK_ENCODED_INVALID =
+ "chrome-native://pdf/link?url=chrome%3A%2F%2Fversion";
private static final String FILE_PATH = "/media/external/downloads/sample.pdf";
private static final String FILE_NAME = "sample.pdf";
private static final String IMAGE_FILE_URL = "file:///media/external/downloads/sample.jpg";
@@ -238,6 +240,18 @@
}
@Test
+ public void testGetPdfReDownloadUrl_Https() {
+ String downloadUrl = PdfUtils.getPdfReDownloadUrl(PDF_LINK_ENCODED);
+ Assert.assertEquals("The re-download url should match", PDF_LINK, downloadUrl);
+ }
+
+ @Test
+ public void testGetPdfReDownloadUrl_Invalid() {
+ String downloadUrl = PdfUtils.getPdfReDownloadUrl(PDF_LINK_ENCODED_INVALID);
+ Assert.assertNull("The re-download url should be null", downloadUrl);
+ }
+
+ @Test
public void testEncodeDecodeUrlWithSpecialCharacter() {
String encodedUrl = PdfUtils.encodePdfPageUrl(CONTENT_URL_SPECIAL_CHARACTER);
String decodedUrl = PdfUtils.decodePdfPageUrl(encodedUrl);
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.
References
On This Page