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 <[email protected]> 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 <[email protected]> Auto-Submit: Stefan Zager <[email protected]> Commit-Queue: Stephen Chenney <[email protected]> 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