Low watch CVSS 4.3 chrome Policy Bypass 📄 Reporter bug report 🔧 Commit mapped

Overview

Low
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient policy enforcement in Search
DescriptionInsufficient policy enforcement in Search
ComponentSearch
Bug ClassPolicy Bypass
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.
Tracker496626029
Fix commit17407bee77cc (chromium/src) +2/-1
CWECWE-693
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-03-26 (per vendor advisory)
Fix landed2026-03-31 (public git)
Disclosed2026-05-05
Patch gap35 days — fix public in source before the advisory

Background

OpenSearch description (OSDD)
a page can advertise a search engine via <link type="application/opensearchdescription+xml" href=...>; Chrome fetches that OSDD URL through TemplateURLFetcher.
`TemplateURLFetcher::RequestDelegate`
the helper that builds and issues the network request to download the OSDD document.
`SiteForCookies`
the network-stack value that identifies the “top-level site” context of a request for SameSite/third-party-cookie decisions; a request whose SiteForCookies matches the target is treated as first-party.
Third-party cookie blocking (3PCB) / SameSite
protections that withhold cookies from cross-site requests; their correctness depends on SiteForCookies reflecting the true initiator, not the target.

Root Cause Analysis

When building the OSDD download request, the code set resource_request->site_for_cookies = net::SiteForCookies::FromUrl(osdd_url), i.e. it derived the cookie context from the target OSDD URL rather than the page that initiated the fetch. This made the request look first-party to the OSDD host, so the request carried that host’s cookies even when third-party-cookie blocking was enabled, violating the invariant that a subresource fetch’s cookie context must reflect the initiator’s top-level site.

The fix changes the assignment to net::SiteForCookies::FromOrigin(initiator), deriving the cookie context from the initiating origin, so the request is correctly treated as same/cross-site relative to the initiator and 3PCB/SameSite rules apply. The enclosing function is not named in the @@ -137 hunk header, but per the commit it is within TemplateURLFetcher::RequestDelegate. This corrects a privacy/policy defect rather than a memory-safety bug.

Key insight
SiteForCookies was derived from the destination URL instead of the initiator, making a third-party OSDD fetch masquerade as first-party; the fix uses SiteForCookies::FromOrigin(initiator) so cookie policy is evaluated against the real initiator.

Attack Path

  1. Host a cross-site OSDD link an attacker page includes <link rel="search" type="application/opensearchdescription+xml" href="https://victim.example/osdd"> pointing at a third-party host where the user holds cookies.
  2. Chrome fetches the OSDD TemplateURLFetcher::RequestDelegate builds the download request for osdd_url.
  3. Mislabeled cookie context pre-patch, site_for_cookies was FromUrl(osdd_url), so the request was treated as first-party to victim.example and sent its cookies even with 3PCB enabled (and could leak SameSite cookies on this credentialed GET).
  4. Cross-site credentialed leak the third-party host receives a credentialed GET it should not have, defeating 3PC/SameSite protections; post-patch the context is FromOrigin(initiator), so the request is correctly cross-site and cookies are withheld.

Impact Assessment

A malicious page could cause credentialed cross-site GET requests to an attacker-chosen host, bypassing third-party-cookie blocking and SameSite protections via the OSDD fetch path; the precondition is only that the user visits a page carrying the crafted OpenSearch <link>. The advisory rates this low severity and classifies it as insufficient policy enforcement in Search; the impact is a privacy/cookie-policy bypass, with no memory-safety or escalation demonstrated. No in-the-wild exploitation is indicated.

Files Changed

  • components/search_engines/template_url_fetcher.cc

Audit Directions

  • `SiteForCookies::FromUrl(target)`
    search for request builders that set site_for_cookies from the destination URL instead of the initiator origin; these can mislabel cross-site fetches as first-party.
  • Browser-initiated subresource fetches
    audit features where the browser process fetches resources on a page’s behalf (search/OSDD, favicons, prefetch, link headers) to confirm they propagate the initiator’s cookie context.
  • Credentialed GETs from page-controlled URLs
    review flows that issue credentialed requests to URLs chosen by page markup, ensuring SameSite/3PCB enforcement is keyed to the initiator.
From 17407bee77cc109057d1b3de9ae3a7d5b339e57a Mon Sep 17 00:00:00 2001
From: Dylan Cutler <[email protected]>
Date: Tue, 31 Mar 2026 15:27:47 -0700
Subject: [PATCH] Use initiator for SiteForCookies in TemplateURLFetcher::RequestDelegate

This fixes a privacy bug that can bypass 3PC protections when blocking
is enabled. This bug allows link with type
"application/opensearchdescription+xml" to send its 1P cookies even
when 3PCB is on. This can also be a SameSite leak which allows
credentialed GET requests.

Bug: 496626029
Change-Id: Ie1a0ef6e2681f593fafb583240eaf7fb0ad5d4da
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7713898
Reviewed-by: Justin Donnelly <[email protected]>
Commit-Queue: Dylan Cutler <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1608144}
---

diff --git a/components/search_engines/template_url_fetcher.cc b/components/search_engines/template_url_fetcher.cc
index 47651252..34bdaf00 100644
--- a/components/search_engines/template_url_fetcher.cc
+++ b/components/search_engines/template_url_fetcher.cc
@@ -137,7 +137,8 @@
   resource_request->resource_type =
       /* blink::mojom::ResourceType::kSubResource */ 6;
   resource_request->destination = network::mojom::RequestDestination::kEmpty;
-  resource_request->site_for_cookies = net::SiteForCookies::FromUrl(osdd_url);
+  resource_request->site_for_cookies =
+      net::SiteForCookies::FromOrigin(initiator);
   simple_url_loader_ = network::SimpleURLLoader::Create(
       std::move(resource_request), kTrafficAnnotation);
   simple_url_loader_->SetAllowHttpErrorResults(true);
Loading diff…

Original Bug Report

reported by [email protected]

3PCD bypass via incorrect site_for_cookies in OSDD fetch

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: A logic error in the OpenSearch Description Document (OSDD) fetcher incorrectly sets the request’s site_for_cookies to the target URL rather than the initiator. This causes the network service to misclassify cross-site OSDD fetches as first-party requests, bypassing Third-Party Cookie Deprecation (3PCD) protections and sending unpartitioned SameSite=None cookies.

Affected files:

  • components/search_engines/template_url_fetcher.cc
  • chrome/browser/ui/search_engines/search_engine_tab_helper.cc

Estimated timestamp from git blame: 2025-01-08

Description

There is a potential logic error in how Chrome fetches OpenSearch Description Documents (OSDD) that allows a cross-site attacker to trigger a credentialed GET request to a victim’s server, bypassing Third-Party Cookie Deprecation (3PCD) protections.

The vulnerability exists in components/search_engines/template_url_fetcher.cc. When a page declares an OSDD via a <link rel='search'> tag, the browser eventually invokes TemplateURLFetcher::ScheduleDownload to fetch the document. In the TemplateURLFetcher::RequestDelegate constructor, the network::ResourceRequest is initialized with:

// components/search_engines/template_url_fetcher.cc:140
resource_request->site_for_cookies = net::SiteForCookies::FromUrl(osdd_url);

Because site_for_cookies is derived directly from the target osdd_url rather than the top-level initiating document’s site, the network service’s cookie policy logic (CookieSettingsBase::GetCookieSettingInternal) incorrectly evaluates IsThirdPartyRequest(url, site_for_cookies) as false. The request is treated as a first-party request, completely bypassing 3PCD blocking logic.

While SameSite=Lax and Strict cookies remain protected because ComputeSameSiteContextForRequest independently verifies the request_initiator (which is correctly set to the attacker’s site), all unpartitioned SameSite=None cookies are included in the outgoing cross-site request.

Potential Reproduction Steps

Note: These are suggested steps based on static analysis, as this agent does not have the ability to run a live proof-of-concept.

  1. Ensure third-party cookies are blocked (default behavior under 3PCD).
  2. A victim logs into victim.com, which sets a SameSite=None; Secure session cookie (without the Partitioned attribute).
  3. The victim navigates to a malicious site hosted at the root path (e.g., https://attacker.com/). Note: The root path is required because SearchEngineTabHelper::GenerateKeywordFromNavigationEntry skips keyword generation for URLs with a path length > 1.
  4. The attacker.com page includes the following tag in its <head>: <link rel='search' type='application/opensearchdescription+xml' href='https://victim.com/api/endpoint'>
  5. The browser processes the tag and dispatches an OSDD fetch to victim.com.
  6. Because of the site_for_cookies flaw, the request will carry the victim’s unpartitioned SameSite=None cookies to victim.com/api/endpoint, successfully bypassing 3PCD.

Impact

  • Cross-site tracking bypass: A victim site can receive a credentialed request whenever a user visits an attacker-controlled page, allowing the victim to track the user across sites despite 3PCD.
  • Blind GET-based CSRF: An attacker can trigger credentialed GET requests to sensitive endpoints on a victim’s site that rely on 3PCD for protection rather than explicit SameSite attributes.
  • Note: The attacker cannot read the response body, as the OSDD fetch response is consumed internally by the browser process (TemplateURLParser).

Suggested Fix

Update TemplateURLFetcher::RequestDelegate to correctly construct the site_for_cookies based on the initiating document’s origin, or explicitly use an empty net::SiteForCookies() for cross-site OSDD fetches so that the network service correctly identifies them as third-party requests and applies 3PCD blocking appropriately:

resource_request->site_for_cookies = net::SiteForCookies::FromOrigin(initiator);

Evaluated with Chrome root at commit: 0eb4855bda702feaaa8b899336664f97e3df88b8


Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. Please feel free to reach out to me if you have concerns or feedback.

View on issue tracker