CVE-2026-13943
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifthird_party/blink/renderer/core/css/style_color.cc |
modified | |
ifthird_party/blink/renderer/core/highlight/highlight_style_utils.cc |
modified |
Files Changed
third_party/blink/renderer/core/css/style_color.ccthird_party/blink/renderer/core/highlight/highlight_style_utils.cc
Patch
From 419269b300439e52cbd983ac957605c099c9be43 Mon Sep 17 00:00:00 2001
From: Kevin Babbitt <kbabbitt@microsoft.com>
Date: Fri, 15 May 2026 09:15:01 -0700
Subject: [PATCH] Ensure is_current_color is initialized for unresolved color functions
Also initialize a related local variable at a call site as
defense-in-depth.
Fixed: 513204116
Change-Id: Ic092fcb1e0b50b61009706408733e2c8a4e23329
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7850514
Commit-Queue: Kevin Babbitt <kbabbitt@microsoft.com>
Reviewed-by: Alison Maher <almaher@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1631337}
---
diff --git a/third_party/blink/renderer/core/css/style_color.cc b/third_party/blink/renderer/core/css/style_color.cc
index c2361fd..37b4eb7 100644
--- a/third_party/blink/renderer/core/css/style_color.cc
+++ b/third_party/blink/renderer/core/css/style_color.cc
@@ -490,6 +490,10 @@
Color StyleColor::Resolve(const Color& current_color,
mojom::blink::ColorScheme color_scheme,
bool* is_current_color) const {
+ if (is_current_color) {
+ *is_current_color = IsCurrentColor();
+ }
+
if (IsUnresolvedColorFunction()) {
Color result =
color_or_unresolved_color_function_.unresolved_color_function->Resolve(
@@ -501,10 +505,6 @@
}
return result;
}
-
- if (is_current_color) {
- *is_current_color = IsCurrentColor();
- }
if (IsCurrentColor()) {
return current_color;
}
diff --git a/third_party/blink/renderer/core/highlight/highlight_style_utils.cc b/third_party/blink/renderer/core/highlight/highlight_style_utils.cc
index 3cb8e21b..3803b47 100644
--- a/third_party/blink/renderer/core/highlight/highlight_style_utils.cc
+++ b/third_party/blink/renderer/core/highlight/highlight_style_utils.cc
@@ -298,7 +298,7 @@
search_text_is_active_match);
}
if (pseudo_style) {
- bool is_current_color;
+ bool is_current_color = false;
Color result = pseudo_style->VisitedDependentColor(To<Longhand>(property),
&is_current_color);
if (!is_current_color) {
Original Bug Report
Uninitialized stack read in StyleColor::Resolve for unresolved color functions
Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the Chrome Security team. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.
Overview: StyleColor::Resolve fails to initialize an optional out-parameter when processing unresolved color functions like color-mix(). This causes callers to branch on uninitialized stack memory, leading to a potential 1-bit information disclosure of stack contents per call.
Affected files:
third_party/blink/renderer/core/css/style_color.ccthird_party/blink/renderer/core/highlight/highlight_style_utils.ccthird_party/blink/renderer/core/css/properties/longhands/longhands_custom.ccthird_party/blink/renderer/core/style/computed_style.cc
Estimated timestamp from git blame: 2022-12-20
Root Cause Analysis
The StyleColor::Resolve() function in third_party/blink/renderer/core/css/style_color.cc is responsible for resolving CSS colors. It includes an optional bool* is_current_color out-parameter intended to inform callers if the resolved color was the currentColor keyword.
However, the function contains an early return when handling unresolved color functions (such as color-mix(), relative colors, or contrast-color()):
// third_party/blink/renderer/core/css/style_color.cc:490
Color StyleColor::Resolve(const Color& current_color,
mojom::blink::ColorScheme color_scheme,
bool* is_current_color) const {
if (IsUnresolvedColorFunction()) {
Color result =
color_or_unresolved_color_function_.unresolved_color_function->Resolve(
current_color);
// ... color space conversion ...
return result; // Potential early return without writing to *is_current_color
}
if (is_current_color) {
*is_current_color = IsCurrentColor(); // Only reached if not an unresolved function
}
// ...
}
When IsUnresolvedColorFunction() is true, the function returns at line 502 without assigning a value to *is_current_color if the pointer was provided.
Uninitialized Read in Callers
Multiple callers in the Blink renderer pass a pointer to an uninitialized local bool to this function. A primary example is HighlightStyleUtils::MaybeResolveColor in third_party/blink/renderer/core/highlight/highlight_style_utils.cc:
// third_party/blink/renderer/core/highlight/highlight_style_utils.cc:300
if (pseudo_style) {
bool is_current_color; // Uninitialized stack variable
Color result = pseudo_style->VisitedDependentColor(To<Longhand>(property),
&is_current_color);
if (!is_current_color) { // Branch on uninitialized stack garbage
return result;
}
}
If the unresolved function is used (e.g., in a highlight pseudo-element), is_current_color remains uninitialized. The branch at line 304 then depends on the previous contents of that stack slot.
Impact and Exploitation Potential
On platforms where stack initialization is disabled (specifically official Android builds, where -ftrivial-auto-var-init=zero is not applied due to binary size concerns), this allows a potential 1-bit information leak of stack contents per call.
An attacker could potentially trigger this by:
- Defining a highlight pseudo-element styled with an unresolved color function:
::highlight(my-h) { background-color: color-mix(in srgb, currentColor 50%, blue); }. - Using a visual oracle (such as the Element Capture API or CSS-based timing side-channels) to observe whether the element was rendered with the
color-mixresult or a fallback color. - Determining the state of the uninitialized stack bit based on the rendered output.
Suggested Potential Steps to Reproduce
- On an Android device running an official Chrome build, navigate to a page that creates a CSS Highlight.
- Apply a style to the highlight using
color-mix():<style> ::highlight(test) { background-color: color-mix(in srgb, currentColor 50%, red); } </style> <div id="target">Sensitive Text</div> <script> const range = new Range(); range.selectNodeContents(document.getElementById('target')); CSS.highlights.set('test', new Highlight(range)); </script> - Observe if rendering inconsistencies occur when previous stack-heavy operations are performed.
Recommended Fix
Ensure *is_current_color is always initialized if the pointer is provided. This can be done at the beginning of StyleColor::Resolve:
Color StyleColor::Resolve(...) const {
if (is_current_color) {
*is_current_color = IsCurrentColor();
}
if (IsUnresolvedColorFunction()) {
// ...
}
// ...
}
Evaluated with Chrome root at commit: b3153093eb3c78c3e88ccf562bcbc20437a04b0e
Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:
- If you are familiar with the severity guidelines, you may adjust the severity.
- If this is a false positive, and there’s no work to be done, please close as WAI.
- If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.
Data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.