Chrome · Canvas › HiC
CVE-2026-113253
UAF in Canvas (HiC)
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Pthird_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc |
modified |
Files Changed
third_party/blink/renderer/core/html/canvas/html_canvas_element_test.ccthird_party/blink/renderer/core/dom/element.cc
Patch
From f8e59690fb80b99d226fe3f6fef0a0d555ef3c81 Mon Sep 17 00:00:00 2001
From: Stefan Zager <szager@chromium.org>
Date: Mon, 12 Oct 2026 07:54:12 -0700
Subject: [PATCH] [HiC] Fix IsInCanvasSubtree for pseudo element on shadow host
Fixed: 553117109
Change-Id: Ib12e73273f23c6488bc1416fac37401eda1bdb4a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8544046
Reviewed-by: Stephen Chenney <schenney@chromium.org>
Auto-Submit: Stefan Zager <szager@chromium.org>
Commit-Queue: Stephen Chenney <schenney@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1716768}
---
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index da3e8bc..9bb4d81 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -4309,7 +4309,8 @@
const auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(*parent);
const bool is_inactive_fallback_content =
slot && !slot->AssignedNodesNoRecalc().empty();
- if (!IsChildOfShadowHost() && !is_inactive_fallback_content) {
+ if (IsPseudoElement() ||
+ (!IsChildOfShadowHost() && !is_inactive_fallback_content)) {
SetIsInCanvasSubtree(true);
}
} else if (!parent && insertion_point.IsDocumentNode()) {
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
index 3307def0a..d6fe2b2 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
@@ -800,4 +800,27 @@
EXPECT_TRUE(grandchild->IsInCanvasSubtree());
}
+TEST_P(HTMLCanvasElementTest, PseudoElementChildOfShadowHost) {
+ GetDocument().body()->SetHTMLUnsafeWithoutTrustedTypes(R"HTML(
+ <style>
+ #host::after {
+ content: "Hello, world!";
+ }
+ </style>
+ <div id="host">
+ <template shadowrootmode="open"></template>
+ </div>
+ <canvas id="c"></canvas>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* host = GetDocument().getElementById(AtomicString("host"));
+ EXPECT_FALSE(host->IsInCanvasSubtree());
+ EXPECT_FALSE(host->GetPseudoElement(kPseudoIdAfter)->IsInCanvasSubtree());
+ GetDocument().getElementById(AtomicString("c"))->appendChild(host);
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_TRUE(host->IsInCanvasSubtree());
+ EXPECT_TRUE(host->GetPseudoElement(kPseudoIdAfter)->IsInCanvasSubtree());
+}
+
} // namespace blink
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
index 3307def0a..d6fe2b2 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
@@ -800,4 +800,27 @@
EXPECT_TRUE(grandchild->IsInCanvasSubtree());
}
+TEST_P(HTMLCanvasElementTest, PseudoElementChildOfShadowHost) {
+ GetDocument().body()->SetHTMLUnsafeWithoutTrustedTypes(R"HTML(
+ <style>
+ #host::after {
+ content: "Hello, world!";
+ }
+ </style>
+ <div id="host">
+ <template shadowrootmode="open"></template>
+ </div>
+ <canvas id="c"></canvas>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* host = GetDocument().getElementById(AtomicString("host"));
+ EXPECT_FALSE(host->IsInCanvasSubtree());
+ EXPECT_FALSE(host->GetPseudoElement(kPseudoIdAfter)->IsInCanvasSubtree());
+ GetDocument().getElementById(AtomicString("c"))->appendChild(host);
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_TRUE(host->IsInCanvasSubtree());
+ EXPECT_TRUE(host->GetPseudoElement(kPseudoIdAfter)->IsInCanvasSubtree());
+}
+
} // namespace blink
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