Chrome · DOM
CVE-2026-79179
Logic Error in DOM
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fthird_party/blink/renderer/core/dom/element_test.cc |
modified |
Files Changed
third_party/blink/renderer/core/dom/element.ccthird_party/blink/renderer/core/dom/element_test.cc
Patch
From 46163c79cd4062bd154712e57e2fbbe2a66846f6 Mon Sep 17 00:00:00 2001 From: David Baron <[email protected]> Date: Tue, 21 Jul 2026 11:42:02 -0700 Subject: [PATCH] Propagate FocusType when forwarding Element::Focus. Propagate FocusType when forwarding Element::Focus to the result of GetFocusableArea() so that we don't incorrectly set WasLastFocusFromUserGesture. Both the fix and the test are AI-authored, though from different AI tools. (I shortened a verbose code comment in the fix.) Fixed: 533079345 Change-Id: Ib44c0ea96a127ccbf5236449c96a0c77e59771e7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8116087 Reviewed-by: Mason Freed <[email protected]> Commit-Queue: David Baron <[email protected]> Cr-Commit-Position: refs/heads/main@{#1665655} --- diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index d484712..ade778c 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc @@ -8356,9 +8356,11 @@ if (Element* new_focus_target = GetFocusableArea()) { // Unlike the specification, we re-run focus() for new_focus_target // because we can't change |this| in a member function. - new_focus_target->Focus(FocusParams( - SelectionBehaviorOnFocus::kReset, mojom::blink::FocusType::kForward, - /*capabilities=*/nullptr, params_to_use.options)); + // Forward the caller's FocusType so we don't set + // WasLastFocusFromUserGesture incorrectly. + new_focus_target->Focus( + FocusParams(SelectionBehaviorOnFocus::kReset, params_to_use.type, + /*capabilities=*/nullptr, params_to_use.options)); } // 2. If new focus target is null, then: // 2.1. If no fallback target was specified, then return. diff --git a/third_party/blink/renderer/core/dom/element_test.cc b/third_party/blink/renderer/core/dom/element_test.cc index 42f169c..9ff0b1e1 100644 --- a/third_party/blink/renderer/core/dom/element_test.cc +++ b/third_party/blink/renderer/core/dom/element_test.cc @@ -1844,4 +1844,39 @@ backdrop->DispatchEvent(*event); } +TEST_F(ElementTest, DelegatesFocusWasLastFocusFromUserGesture) { + SetBodyContent("<div id='host'></div>"); + ShadowRoot* shadow_root = + SetShadowContent("<div id='probe' contenteditable='true'></div>", "host"); + shadow_root->SetDelegatesFocus(true); + UpdateAllLifecyclePhasesForTest(); + + Element* host = GetElementById("host"); + Element* probe = shadow_root->getElementById(AtomicString("probe")); + ASSERT_TRUE(host); + ASSERT_TRUE(probe); + + EXPECT_FALSE(probe->WasLastFocusFromUserGesture()); + + host->Focus(); + EXPECT_EQ(probe, GetDocument().FocusedElement()); + EXPECT_FALSE(probe->WasLastFocusFromUserGesture()); + + probe->blur(); + EXPECT_NE(probe, GetDocument().FocusedElement()); + + host->Focus(FocusParams(SelectionBehaviorOnFocus::kRestore, + mojom::blink::FocusType::kScript, nullptr)); + EXPECT_EQ(probe, GetDocument().FocusedElement()); + EXPECT_FALSE(probe->WasLastFocusFromUserGesture()); + + probe->blur(); + EXPECT_NE(probe, GetDocument().FocusedElement()); + + host->Focus(FocusParams(SelectionBehaviorOnFocus::kRestore, + mojom::blink::FocusType::kMouse, nullptr)); + EXPECT_EQ(probe, GetDocument().FocusedElement()); + EXPECT_TRUE(probe->WasLastFocusFromUserGesture()); +} + } // namespace blink
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/third_party/blink/renderer/core/dom/element_test.cc b/third_party/blink/renderer/core/dom/element_test.cc
index 42f169c..9ff0b1e1 100644
--- a/third_party/blink/renderer/core/dom/element_test.cc
+++ b/third_party/blink/renderer/core/dom/element_test.cc
@@ -1844,4 +1844,39 @@
backdrop->DispatchEvent(*event);
}
+TEST_F(ElementTest, DelegatesFocusWasLastFocusFromUserGesture) {
+ SetBodyContent("<div id='host'></div>");
+ ShadowRoot* shadow_root =
+ SetShadowContent("<div id='probe' contenteditable='true'></div>", "host");
+ shadow_root->SetDelegatesFocus(true);
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* host = GetElementById("host");
+ Element* probe = shadow_root->getElementById(AtomicString("probe"));
+ ASSERT_TRUE(host);
+ ASSERT_TRUE(probe);
+
+ EXPECT_FALSE(probe->WasLastFocusFromUserGesture());
+
+ host->Focus();
+ EXPECT_EQ(probe, GetDocument().FocusedElement());
+ EXPECT_FALSE(probe->WasLastFocusFromUserGesture());
+
+ probe->blur();
+ EXPECT_NE(probe, GetDocument().FocusedElement());
+
+ host->Focus(FocusParams(SelectionBehaviorOnFocus::kRestore,
+ mojom::blink::FocusType::kScript, nullptr));
+ EXPECT_EQ(probe, GetDocument().FocusedElement());
+ EXPECT_FALSE(probe->WasLastFocusFromUserGesture());
+
+ probe->blur();
+ EXPECT_NE(probe, GetDocument().FocusedElement());
+
+ host->Focus(FocusParams(SelectionBehaviorOnFocus::kRestore,
+ mojom::blink::FocusType::kMouse, nullptr));
+ EXPECT_EQ(probe, GetDocument().FocusedElement());
+ EXPECT_TRUE(probe->WasLastFocusFromUserGesture());
+}
+
} // 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