Chrome · CSS
CVE-2026-14085
Logic Error in CSS
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifthird_party/blink/renderer/core/style/computed_style.cc |
modified |
Files Changed
third_party/blink/renderer/core/paint/gap_decorations_painter.ccthird_party/blink/renderer/core/style/computed_style.ccthird_party/blink/renderer/core/style/computed_style.hthird_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp-ref.htmlthird_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp.html
Patch
From 7aed80d9d964be9742fe639ba60c266a77edbaa9 Mon Sep 17 00:00:00 2001 From: Javier Contreras Tenorio <[email protected]> Date: Thu, 21 May 2026 08:19:54 -0700 Subject: [PATCH] [gap-decorations] Fix :visited alpha side-channel in gap decoration colors This CL clamps the visited gap color's alpha to the unvisited gap color's alpha, matching the pattern used in VisitedDependentColor. This was the exact suggested fix in the linked bug,it was verified as well in that same bug Fixed: 513155863 Change-Id: Ie587fea07f37346b2648a182ce6f39e662c3141c Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7855943 Reviewed-by: Alison Maher <[email protected]> Commit-Queue: Javier Contreras <[email protected]> Cr-Commit-Position: refs/heads/main@{#1634299} --- diff --git a/third_party/blink/renderer/core/paint/gap_decorations_painter.cc b/third_party/blink/renderer/core/paint/gap_decorations_painter.cc index 509dd2a9..2cebb18e 100644 --- a/third_party/blink/renderer/core/paint/gap_decorations_painter.cc +++ b/third_party/blink/renderer/core/paint/gap_decorations_painter.cc @@ -273,7 +273,7 @@ } const StyleColor rule_color = color_iterator.Next(); const Color resolved_rule_color = - style.VisitedDependentGapColor(rule_color, style, is_column_gap); + style.VisitedDependentGapColor(rule_color, is_column_gap); const EBorderStyle rule_style = ComputedStyle::CollapsedBorderStyle(style_iterator.Next()); const LayoutUnit rule_thickness = LayoutUnit(width_iterator.Next()); diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 1e808218..73df192 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc @@ -2533,6 +2533,15 @@ blink::Color unvisited_color = color_property.ColorIncludingFallback(false, *this, is_current_color); + return VisitedDependentColor(unvisited_color, color_property, + is_current_color); +} + +Color ComputedStyle::VisitedDependentColor(const blink::Color& unvisited_color, + const Longhand& color_property, + bool* is_current_color) const { + DCHECK(!color_property.IsVisited()); + if (InsideLink() != EInsideLink::kInsideVisitedLink) { return unvisited_color; } @@ -2572,7 +2581,6 @@ blink::Color ComputedStyle::VisitedDependentGapColor( const StyleColor& gap_color, - const ComputedStyle& style, bool is_column_rule) const { CHECK(RuntimeEnabledFeatures::CSSGapDecorationEnabled()); blink::Color unvisited_gap_color; @@ -2587,27 +2595,17 @@ GetCurrentColor(), UsedColorScheme(), /*is_current_color=*/nullptr); } - if (InsideLink() != EInsideLink::kInsideVisitedLink) { - return unvisited_gap_color; - } - - // For `row-rule-color`, :visited styling is not supported. + // For `row-rule-color`, :visited styling is not supported. We currently + // support visited styling for `column-rule-color` due to backwards + // compatibility (before CSSGapDecorations). As a result, it is important + // to note that we only supported visited styling for single values, + // rather than value lists (which GapDecorations introduced). if (!is_column_rule) { return unvisited_gap_color; } - blink::Color visited_gap_color; - if (ShouldForceColor(gap_color)) { - visited_gap_color = - GetInternalForcedVisitedCurrentColor(/*is_current_color=*/nullptr); - } else { - visited_gap_color = - style.InternalVisitedColumnRuleColor().GetLegacyValue().Resolve( - GetInternalVisitedCurrentColor(), UsedColorScheme(), - /*is_current_color=*/nullptr); - } - - return visited_gap_color; + return VisitedDependentColor(unvisited_gap_color, + GetCSSPropertyColumnRuleColor()); } blink::Color ComputedStyle::VisitedDependentContextFill( diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 831d6b9..eb420dc 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h @@ -2453,9 +2453,13 @@ const Longhand& color_property, bool* is_current_color = nullptr) const; + CORE_EXPORT blink::Color VisitedDependentColor( + const blink::Color& unvisited_color, + const Longhand& color_property, + bool* is_current_color = nullptr) const; + // Used to resolve gap decoration colors for painting. CORE_EXPORT blink::Color VisitedDependentGapColor(const StyleColor& gap_color, - const ComputedStyle& style, bool is_column_rule) const; // Used to resolve 'context-fill' and 'context-stroke' paints diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp-ref.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp-ref.html new file mode 100644 index 0000000..721286b026 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp-ref.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-gaps-1/"> +<link rel="author" title="Javier Contreras" href="mailto:[email protected]"> +<style> + body { + margin: 0px; + } + .grid-container { + display: grid; + grid-gap: 20px; + grid-template-columns: 100px 100px; + height: 100px; + + column-rule-color: rgba(0, 0, 255, 0.5); + column-rule-style: solid; + column-rule-width: 10px; + } + .item { + background: white; + } +</style> +<div class="grid-container"> + <div class="item"></div> + <div class="item"></div> +</div> diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp.html new file mode 100644 index 0000000..fc169d0bb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title> + CSS Gap Decorations: :visited column-rule-color alpha is clamped to unvisited alpha. +</title> +<link rel="help" href="https://drafts.csswg.org/css-gaps-1/"> +<link rel="match" href="grid-gap-decorations-visited-alpha-clamp-ref.html"> +<link rel="author" title="Javier Contreras" href="mailto:[email protected]"> +<style> + body { + margin: 0px; + } + .grid-container { + display: grid; + grid-gap: 20px; + grid-template-columns: 100px 100px; + height: 100px; + + column-rule-color: rgba(255, 0, 0, 0.5); + column-rule-style: solid; + column-rule-width: 10px; + } + .item { + background: white; + } + .grid-link:visited .grid-container { + column-rule-color: rgba(0, 0, 255, 1.0); + } +</style> +<a href="" class="grid-link"> + <div class="grid-container"> + <div class="item"></div> + <div class="item"></div> + </div> +</a>
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp-ref.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp-ref.html new file mode 100644 index 0000000..721286b026 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp-ref.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-gaps-1/"> +<link rel="author" title="Javier Contreras" href="mailto:[email protected]"> +<style> + body { + margin: 0px; + } + .grid-container { + display: grid; + grid-gap: 20px; + grid-template-columns: 100px 100px; + height: 100px; + + column-rule-color: rgba(0, 0, 255, 0.5); + column-rule-style: solid; + column-rule-width: 10px; + } + .item { + background: white; + } +</style> +<div class="grid-container"> + <div class="item"></div> + <div class="item"></div> +</div> diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp.html new file mode 100644 index 0000000..fc169d0bb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title> + CSS Gap Decorations: :visited column-rule-color alpha is clamped to unvisited alpha. +</title> +<link rel="help" href="https://drafts.csswg.org/css-gaps-1/"> +<link rel="match" href="grid-gap-decorations-visited-alpha-clamp-ref.html"> +<link rel="author" title="Javier Contreras" href="mailto:[email protected]"> +<style> + body { + margin: 0px; + } + .grid-container { + display: grid; + grid-gap: 20px; + grid-template-columns: 100px 100px; + height: 100px; + + column-rule-color: rgba(255, 0, 0, 0.5); + column-rule-style: solid; + column-rule-width: 10px; + } + .item { + background: white; + } + .grid-link:visited .grid-container { + column-rule-color: rgba(0, 0, 255, 1.0); + } +</style> +<a href="" class="grid-link"> + <div class="grid-container"> + <div class="item"></div> + <div class="item"></div> + </div> +</a>
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