Low chrome Logic Error 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactSide-channel information leakage in CSS
DescriptionSide-channel information leakage in CSS
ComponentCSS
Bug ClassLogic Error
Tracker513155863
Fix commit7aed80d9d964 (chromium/src) +81/-20
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Changed Functions

FunctionChangeNotes
if
third_party/blink/renderer/core/style/computed_style.cc
modified

Files Changed

  • third_party/blink/renderer/core/paint/gap_decorations_painter.cc
  • third_party/blink/renderer/core/style/computed_style.cc
  • third_party/blink/renderer/core/style/computed_style.h
  • third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp-ref.html
  • third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-visited-alpha-clamp.html
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.