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 <[email protected]> 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 <[email protected]> Reviewed-by: Sirisha Kavuluru <[email protected]> Commit-Queue: Shu Yang <[email protected]> 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