Chrome · Chromium
CVE-2025-4664
Logic Error in Chromium
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
switchthird_party/blink/renderer/core/loader/preload_helper.cc |
modified |
Files Changed
third_party/blink/common/features.ccthird_party/blink/public/common/features.hthird_party/blink/renderer/core/loader/preload_helper.cc
Patch
From 1ea5b9417cd993d0ddb15fec186fed016198050c Mon Sep 17 00:00:00 2001 From: Takashi Nakayama <[email protected]> Date: Tue, 09 Dec 2025 22:48:32 -0800 Subject: [PATCH] Add features to restrict Link headers on subresource responses This CL implements a feature flag to partially disable HTTP Link headers on subresource responses for experiments. The prepared options are based on a proposal doc [1]. [1] https://docs.google.com/document/d/1OeqpA9JoCXrgIMpq-ujLuZF1tG9MNF5SA0zTuIFtZis/edit?usp=sharing Bug: 415810136 Change-Id: I473313c350d3acf1c2a5808c551152a47e69ac21 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7172079 Commit-Queue: Takashi Nakayama <[email protected]> Reviewed-by: Hiroshige Hayashizaki <[email protected]> Cr-Commit-Position: refs/heads/main@{#1556546} --- diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 311a725..03ce59c 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc @@ -2084,6 +2084,29 @@ BASE_FEATURE(kResourceFetcherStoresStrongReferences, base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kRestrictLinkHeaderOnSubresource, + base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE_PARAM(bool, + kRestrictLinkHeaderOnSubresourceCompressionDictionary, + &kRestrictLinkHeaderOnSubresource, + "disable_compression_dictionary", + false); +BASE_FEATURE_PARAM(bool, + kRestrictLinkHeaderOnSubresourceCrossOrigin, + &kRestrictLinkHeaderOnSubresource, + "disable_cross_origin", + false); +BASE_FEATURE_PARAM(bool, + kRestrictLinkHeaderOnSubresourceNetworkHint, + &kRestrictLinkHeaderOnSubresource, + "disable_network_hint", + false); +BASE_FEATURE_PARAM(bool, + kRestrictLinkHeaderOnSubresourceResourceLoad, + &kRestrictLinkHeaderOnSubresource, + "disable_resource_load", + false); + BASE_FEATURE(kRestrictSpellingAndGrammarHighlights, base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE_PARAM(bool, diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index d3f5e38..07085cd 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h @@ -1616,6 +1616,27 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE( kResourceFetcherStoresStrongReferences); +// Aggregated flag for the restriction on HTTP Link headers on subresource +// responses. See crbug.com/417529151 for details. +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kRestrictLinkHeaderOnSubresource); +// Disables only "rel=compression-dictionary". +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE_PARAM( + bool, + kRestrictLinkHeaderOnSubresourceCompressionDictionary); +// Disables all types of chained-preloads from cross-origin subresource +// responses. +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE_PARAM( + bool, + kRestrictLinkHeaderOnSubresourceCrossOrigin); +// Disables "rel=dns-prefetch" and "rel=preconnect". +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE_PARAM( + bool, + kRestrictLinkHeaderOnSubresourceNetworkHint); +// Disables "rel=preload", "rel=modulepreload", and "rel=prefetch". +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE_PARAM( + bool, + kRestrictLinkHeaderOnSubresourceResourceLoad); + // When enabled, it adds Payto URI Scheme to the safe list for // registerProtocolHandler. This feature is disabled by default // Payto URI Scheme explanation https://datatracker.ietf.org/doc/html/rfc8905 diff --git a/third_party/blink/renderer/core/loader/preload_helper.cc b/third_party/blink/renderer/core/loader/preload_helper.cc index cfc2dabe..75637de8 100644 --- a/third_party/blink/renderer/core/loader/preload_helper.cc +++ b/third_party/blink/renderer/core/loader/preload_helper.cc @@ -191,7 +191,12 @@ as == "video" || as == "worker" || as == "xslt"; } -bool IsNetworkHintAllowed(PreloadHelper::LoadLinksFromHeaderMode mode) { +bool IsNetworkHintAllowed(PreloadHelper::LoadLinksFromHeaderMode mode, + bool is_header_on_subresource) { + if (is_header_on_subresource && + blink::features::kRestrictLinkHeaderOnSubresourceNetworkHint.Get()) { + return false; + } switch (mode) { case PreloadHelper::LoadLinksFromHeaderMode::kDocumentBeforeCommit: return true; @@ -211,7 +216,12 @@ } bool IsResourceLoadAllowed(PreloadHelper::LoadLinksFromHeaderMode mode, - bool is_viewport_dependent) { + bool is_viewport_dependent, + bool is_header_on_subresource) { + if (is_header_on_subresource && + blink::features::kRestrictLinkHeaderOnSubresourceResourceLoad.Get()) { + return false; + } switch (mode) { case PreloadHelper::LoadLinksFromHeaderMode::kDocumentBeforeCommit: return false; @@ -231,7 +241,13 @@ } bool IsCompressionDictionaryLoadAllowed( - PreloadHelper::LoadLinksFromHeaderMode mode) { + PreloadHelper::LoadLinksFromHeaderMode mode, + bool is_header_on_subresource) { + if (is_header_on_subresource && + blink::features::kRestrictLinkHeaderOnSubresourceCompressionDictionary + .Get()) { + return false; + } // Document header can trigger dictionary load after the page load completes. // Subresources header can trigger dictionary load if it is not from the // memory cache. @@ -828,11 +844,12 @@ if (!header.Valid() || header.Url().empty() || header.Rel().empty()) { continue; } - bool is_network_hint_allowed = IsNetworkHintAllowed(mode); - bool is_resource_load_allowed = - IsResourceLoadAllowed(mode, header.IsViewportDependent()); + bool is_network_hint_allowed = + IsNetworkHintAllowed(mode, is_subresource_load); + bool is_resource_load_allowed = IsResourceLoadAllowed( + mode, header.IsViewportDependent(), is_subresource_load); bool is_compression_dictionary_load_allowed = - IsCompressionDictionaryLoadAllowed(mode); + IsCompressionDictionaryLoadAllowed(mode, is_subresource_load); if (!is_network_hint_allowed && !is_resource_load_allowed && !is_compression_dictionary_load_allowed) { // Skip this `header`; it won't initiate any types of preloading. @@ -856,6 +873,10 @@ .SetOriginStatusOnSubresource(base::to_underlying(origin_status)) .Record(document->UkmRecorder()); } + if (is_subresource_load && !from_same_origin && + blink::features::kRestrictLinkHeaderOnSubresourceCrossOrigin.Get()) { + continue; + } // For security purposes, set `referrerpolicy: "no-referrer"` in link loads // from subresources. See https://crbug.com/415810136 for details.
Loading diff…
Original Bug Report
reported by [email protected]
Cross-origin image loaded in <img> tag can make additional request and leak referrer
VULNERABILITY DETAILS
See this tweet.
Chrome allows triggering additional network requests from subresources (e.g. images) by following Link header. AFAIK, resources loaded in <img> tag is inert, and therefore it can’t make additional network requests, animate (in case of SVG), etc.
This allows leaking referrer, which should be origin when cross-origin by default, which seems to be bypassed here.
CREDIT INFORMATION
Reporter credit: https://x.com/slonser_
References
On This Page