Low watch CVSS 4.3 chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Low
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Extensions
DescriptionInappropriate implementation in Extensions
ComponentExtensions
Sub-componentPDF
Bug ClassLogic Error
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker416942878
Fix commitd2d70e969646 (chromium/src) +15/-5
CWECWE-79 (Cross-site scripting)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CISA KEVNot listed
CreditedVincent Dragnea
Reported2025-05-11 · bounty $2000 (per vendor advisory)
Fix landed2025-06-10 (public git)
Disclosed2025-08-05
Patch gap56 days — fix public in source before the advisory

Background

`ExtensionTabUtil::OpenTab()`
the helper backing chrome.tabs.create() that builds NavigateParams and starts a navigation into a newly created tab.
`TabsUpdateFunction::UpdateURL()`
the helper backing chrome.tabs.update() that navigates the current tab, and which already set renderer-initiated navigation parameters.
PDF Viewer extension
a built-in Chrome extension (id extension_misc::kPdfExtensionId) that renders PDFs and uses chrome.tabs.create()/chrome.tabs.update() to open links from within a document.
`NavigateParams` (`is_renderer_initiated`, `initiator_origin`, `source_site_instance`)
fields that record who initiated a navigation, used by browser-side security checks that depend on the initiator’s origin.

Root Cause Analysis

When the PDF Viewer opened a link in a new tab via chrome.tabs.create(), control reached ExtensionTabUtil::OpenTab(), which built a NavigateParams without marking the navigation as renderer-initiated and without attaching the PDF extension’s initiator_origin and source_site_instance. This is inconsistent with same-tab link navigations, which flow through TabsUpdateFunction::UpdateURL() where those parameters are already set. The violated invariant is that a navigation triggered by content inside the PDF Viewer should be attributed to the PDF extension’s origin consistently regardless of whether it targets the current tab or a new tab; treating the new-tab case as effectively browser-initiated with no initiator misrepresents its provenance to downstream navigation/security logic.

The fix copies the UpdateURL() behavior into OpenTab() for the PDF extension only: it sets navigate_params.is_renderer_initiated = true, navigate_params.initiator_origin = extension->origin(), and creates a matching source_site_instance. The change also hoists function->extension() into a local extension and reuses it, keeping the incognito split-mode branch and the new PDF branch reading the same value.

Key insight
New-tab navigations from the PDF Viewer were not tagged with the extension’s initiator origin/site instance the way same-tab navigations were, so the fix makes OpenTab() set the same renderer-initiated parameters as UpdateURL() for the PDF extension, giving both paths consistent, correctly attributed navigation provenance.

Attack Path

  1. Trigger a PDF Viewer new-tab navigation A link inside a rendered PDF (or the viewer UI) causes the PDF Viewer extension to call chrome.tabs.create() for the target URL, reaching ExtensionTabUtil::OpenTab().
  2. Navigation built without initiator attribution Pre-patch, OpenTab() produced a NavigateParams lacking is_renderer_initiated, initiator_origin, and source_site_instance, so the resulting navigation was not attributed to the PDF extension’s origin.
  3. Inconsistent security handling Because initiator-dependent navigation checks saw no (or a wrong) initiator, the new-tab navigation was handled differently from the equivalent same-tab navigation, an inappropriate implementation the advisory flags in Extensions.
  4. Downstream misattribution Any concrete abuse (e.g. origin/URL spoofing or bypass of an initiator-based restriction) that follows from the missing attribution is (inferred), as the patch demonstrates only the parameter inconsistency, not a specific downstream sink.

Impact Assessment

An attacker whose content is processed by the PDF Viewer could cause a new-tab navigation to be launched without correct initiator-origin attribution in the browser process, diverging from the security handling applied to normal PDF navigations. The precondition is invoking the PDF Viewer’s new-tab open path (chrome.tabs.create()). The advisory rates this an inappropriate implementation (logic error) in Extensions with no stated in-the-wild exploitation; any spoofing or restriction-bypass consequence is (inferred).

Changed Functions

FunctionChangeNotes
if
chrome/browser/extensions/extension_tab_util.cc
modified

Files Changed

  • chrome/browser/extensions/extension_tab_util.cc

Audit Directions

  • Divergent navigation entry points
    Compare chrome.tabs.create()/OpenTab() and chrome.tabs.update()/UpdateURL() (and other navigation helpers) for asymmetric setting of is_renderer_initiated, initiator_origin, and source_site_instance.
  • Missing initiator origin on privileged-origin navigations
    Look for navigations started on behalf of built-in extensions or WebUI that omit the initiator’s origin/site instance, weakening initiator-dependent checks.
  • Special-cased single-caller fixes
    Where a fix is applied to only one caller (here the PDF extension) for compatibility, audit the other callers of the same helper for the same unattributed-navigation gap.
From d2d70e969646e9ba1c5f4a0ad586fe327eefc7b6 Mon Sep 17 00:00:00 2001
From: Lei Zhang <thestig@chromium.org>
Date: Mon, 09 Jun 2025 18:05:21 -0700
Subject: [PATCH] [PDF] Perform navigations from the PDF Viewer more consistently

The PDF Viewer uses chrome.tabs.update() and chrome.tabs.create() to
navigate to links in the current tab and in a new tab, respectively. To
make their behavior more consistent, copy navigation params from
TabsUpdateFunction::UpdateURL() to ExtensionTabUtil::OpenTab().

It may be beneficial for ExtensionTabUtil::OpenTab() to use the PDF
Viewer behavior for all chrome.tabs.create() calls. But for now, only
apply it to the PDF Viewer to avoid potential compatibility issues.

Bug: 416942878
Change-Id: I797b9efa38872fa9269ba01cde752e0796dd2ef8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6629248
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Nasko Oskov <nasko@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1471532}
---

diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index 9829dce..ae5337d 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -314,11 +314,11 @@
   // -title
   // -favIconUrl
 
+  auto* const extension = function->extension();
   GURL url(chrome::kChromeUINewTabURL);
   if (params.url) {
-    ASSIGN_OR_RETURN(url,
-                     PrepareURLForNavigation(*params.url, function->extension(),
-                                             function->browser_context()));
+    ASSIGN_OR_RETURN(url, PrepareURLForNavigation(*params.url, extension,
+                                                  function->browser_context()));
   }
 
   // Default to foreground for the new tab. The presence of 'active' property
@@ -336,8 +336,7 @@
   // We can't load extension URLs into incognito windows unless the extension
   // uses split mode. Special case to fall back to a tabbed window.
   if (url.SchemeIs(kExtensionScheme) &&
-      (!function->extension() ||
-       !IncognitoInfo::IsSplitMode(function->extension())) &&
+      (extension || !IncognitoInfo::IsSplitMode(extension)) &&
       browser->profile()->IsOffTheRecord()) {
     Profile* original_profile = browser->profile()->GetOriginalProfile();
 
@@ -380,6 +379,17 @@
   // likely a re-write of how this navigation is called to be compatible with
   // the navigation capturing behavior.
   navigate_params.pwa_navigation_capturing_force_off = true;
+
+  // Treat PDF open-in-new-window navigations consistently with other PDF
+  // navigations, as done in TabsUpdateFunction::UpdateURL().
+  if (extension && extension->id() == extension_misc::kPdfExtensionId) {
+    navigate_params.is_renderer_initiated = true;
+    navigate_params.initiator_origin = extension->origin();
+    navigate_params.source_site_instance = content::SiteInstance::CreateForURL(
+        function->browser_context(),
+        navigate_params.initiator_origin->GetURL());
+  }
+
   base::WeakPtr<content::NavigationHandle> handle = Navigate(&navigate_params);
   if (handle && params.bookmark_id) {
     ChromeNavigationUIData* ui_data =
Loading diff…

Original Bug Report

reported by gn...@gmail.com

SameSite Strict cookies are included when middle clicking a link to another site in a PDF document


Report description

SameSite Strict cookies are included when middle clicking a link to another site in a PDF document


Bug location

Where do you want to report your vulnerability?

Chrome VRP – Report security issues affecting the Chrome browser. See program rules


The problem

Please describe the technical details of the vulnerability

Steps to reproduce:

  • Navigate to a page that has set a cookie with SameSite=Strict
  • Create a PDF document with a link to that page
  • Open that PDF in Chrome, and open the link in a new tab with a middle mouse click
  • The SameSite cookie is included with the request for that tab, even if the PDF was served from a different site.

The above steps detail the basic idea, however for ease of reproduction I have also created a Flask application to demonstrate the behaviour at the following GitHub repository: https://github.com/gnea-sec/samesite-demo

  • Add an entry to your hosts file, such as notlocalhost, that also points to 127.0.0.1.
  • Launch the server, and navigate to http://localhost:8181/setcookie
    • This sets a cookie with SameSite=Strict
  • Verify that the cookie is set at http://localhost:8181/showcookie
  • Navigate to http://notlocalhost:8181/pdflink
    • Note that this is on a separate domain notlocalhost, and following links from this site should not include the SameSite cookie.
  • Middle mouse click on the link to open it in a new tab. Note that the tab indicates that the SameSite cookie was received.
    • Opening the link by left clicking, or right clicking and selecting “Open link in new tab” does not include the cookie.
  • The origin of the link can be further obfuscated, such as by loading it in an iframe, as demonstrated in the mentioned application at http://notlocalhost:8181/frame

The attached video samesite-example.mp4 shows this server being used to demonstrate the issue. It shows a regular HTML link that does not include the SameSite cookie when followed from another site, and then shows the PDF document being served from another site. When the PDF link is followed with a left click, or right click and open in new tab, it does not include the SameSite cookie. However, when the link in a PDF document is middle clicked, it does include the SameSite cookie.

Impact analysis – Please briefly explain who can exploit the vulnerability, and what they gain when doing so

SameSite Strict cookies should not be included when following links from another site. If a website has functionality that can perform a sensitive action with a GET request, and it is relying on a SameSite cookie to prevent unauthorized access, then this can be used in social engineering attacks against users of that site. Any malicious actor would be able to target users of websites that are vulnerable in this way, and use this issue to exploit CSRF vulnerabilities.

This issue can be exploited to circumvent SameSite cookie protections. Following a link from another site should not include SameSite cookies. While a secure web application should not be significantly impacted by this issue, it has the potential to exacerbate certain misconfigurations. For instance, if a GET request is able to perform a sensitive action (it would not be unheard of for an endpoint intended to receive POST requests to also accept GET), then a malicious site could display a PDF loaded in an iframe, and use social engineering techniques to convince users to middle click on the link. A targeted phishing campaign does not need to fool everyone, it just needs to fool one person.


The cause

What version of Chrome have you found the security issue in?

Version 136.0.7103.93 (Official Build) (64-bit)

No, it is not related to a crash.

Choose the type of vulnerability

Cross-site request forgery (CSRF)

How would you like to be publicly acknowledged for your report?

Vincent Dragnea

View on issue tracker