Chrome · IFrame Sandbox
CVE-2026-8563
Sandbox Escape in IFrame Sandbox
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
testthird_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-area-use-counter.html |
modified | |
testthird_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-svg-anchor-use-counter.html |
modified | |
testthird_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-use-counter.html |
modified |
Files Changed
third_party/blink/public/mojom/use_counter/metrics/web_feature.mojomthird_party/blink/renderer/core/html/html_anchor_element.ccthird_party/blink/renderer/core/svg/svg_a_element.ccthird_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-area-use-counter.htmlthird_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-svg-anchor-use-counter.htmlthird_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-use-counter.htmltools/metrics/histograms/metadata/blink/enums.xml
Patch
From d6cf22406be1252f030a6a75529bc7570fab675b Mon Sep 17 00:00:00 2001 From: Emily Stark <[email protected]> Date: Tue, 10 Mar 2026 08:16:16 -0700 Subject: [PATCH] Measure click events from synthesized middle-clicks Chrome will dispatch a synthesized "click" event with {"button": 1} to an anchor element, but per spec it is unclear whether this should be allowed. Measure how common this is so that we can hopefully deprecate. Bug: 40061220,40262435 Change-Id: I7643f0a38e2d43eab57c49e5a024482ac3fd1393 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7643254 Reviewed-by: Mason Freed <[email protected]> Commit-Queue: Emily Stark <[email protected]> Cr-Commit-Position: refs/heads/main@{#1597071} --- diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index cb23d2a..da550c03 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom @@ -5133,6 +5133,9 @@ kHTMLInputElementTypeChangedWhileConnected = 5816, kHTMLButtonElementTypeChangedWhileDisconnected = 5817, kHTMLInputElementTypeChangedWhileDisconnected = 5818, + kSynthesizedMiddleClickAnchor = 5819, + kSynthesizedMiddleClickArea = 5820, + kSynthesizedMiddleClickSVGAnchor = 5821, // Add new features immediately above this line. Don't change the existing // numbers of any item, and don't reuse removed slots. Also don't add extra diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc index eb9ae05..ad38749 100644 --- a/third_party/blink/renderer/core/html/html_anchor_element.cc +++ b/third_party/blink/renderer/core/html/html_anchor_element.cc @@ -550,6 +550,22 @@ void HTMLAnchorElementBase::HandleClick(MouseEvent& event) { event.SetDefaultHandled(); + // It's unclear whether synthesized middle-button "click" events should be + // allowed to be dispatched and create a navigation. Measure how common this + // is to see if we can disallow it. Per Pointer Events: "The click event + // should only be fired for the primary pointer button (i.e., when button + // value is 0, buttons value is 1). Secondary buttons (like the middle or + // right button on a standard mouse) MUST NOT fire click events." + // (https://w3c.github.io/pointerevents/#dfn-click) + if (event.type() == event_type_names::kClick && !event.isTrusted() && + event.button() == + static_cast<int16_t>(WebPointerProperties::Button::kMiddle)) { + UseCounter::Count(GetDocument(), + IsA<HTMLAreaElement>(this) + ? WebFeature::kSynthesizedMiddleClickArea + : WebFeature::kSynthesizedMiddleClickAnchor); + } + LocalDOMWindow* window = GetDocument().domWindow(); if (!window) return; diff --git a/third_party/blink/renderer/core/svg/svg_a_element.cc b/third_party/blink/renderer/core/svg/svg_a_element.cc index 26992db..1a4e2e8 100644 --- a/third_party/blink/renderer/core/svg/svg_a_element.cc +++ b/third_party/blink/renderer/core/svg/svg_a_element.cc @@ -48,6 +48,7 @@ #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/core/xlink_names.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" +#include "third_party/blink/renderer/platform/instrumentation/use_counter.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h" #include "third_party/blink/renderer/platform/weborigin/security_policy.h" @@ -124,6 +125,20 @@ } if (IsLinkClick(event)) { + // It's unclear whether synthesized middle-button "click" events should be + // allowed to be dispatched and create a navigation. Measure how common + // this is to see if we can disallow it. Per Pointer Events: "The click + // event should only be fired for the primary pointer button (i.e., when + // button value is 0, buttons value is 1). Secondary buttons (like the + // middle or right button on a standard mouse) MUST NOT fire click + // events." (https://w3c.github.io/pointerevents/#dfn-click) + if (event.type() == event_type_names::kClick && !event.isTrusted() && + To<MouseEvent>(event).button() == + static_cast<int16_t>(WebPointerProperties::Button::kMiddle)) { + UseCounter::Count(GetDocument(), + WebFeature::kSynthesizedMiddleClickSVGAnchor); + } + StringView url = StripLeadingAndTrailingHtmlSpaces(HrefString()); if (url.starts_with('#')) { diff --git a/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-area-use-counter.html b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-area-use-counter.html new file mode 100644 index 0000000..d148cad --- /dev/null +++ b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-area-use-counter.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> + +<body> + <map id="m" name="m"> + <area href="" shape="default"> + </map> + <img src="" usemap="#m" id="image"> + <script> + const kSynthesizedMiddleClickArea = 5820; + + test(function () { + const area = document.querySelector('area'); + + internals.clearUseCounter(document, kSynthesizedMiddleClickArea); + assert_false(internals.isUseCounted(document, kSynthesizedMiddleClickArea), "Area should not be counted initially"); + const event = new MouseEvent('click', { + button: 1 // Middle button + }); + area.dispatchEvent(event); + assert_true(internals.isUseCounted(document, kSynthesizedMiddleClickArea), "Area should be counted after synthesized middle click"); + }, "Synthesized middle click on area should trigger UseCounter"); + </script> +</body> +</html> \ No newline at end of file diff --git a/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-svg-anchor-use-counter.html b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-svg-anchor-use-counter.html new file mode 100644 index 0000000..3596910 --- /dev/null +++ b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-svg-anchor-use-counter.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> + +<body> + <svg xmlns="http://www.w3.org/2000/svg"> + <a href="" id="svglink"><text>link</text></a> + </svg> + <script> + const kSynthesizedMiddleClickSVGAnchor = 5821; + + test(function () { + const link = document.getElementById('svglink'); + + internals.clearUseCounter(document, kSynthesizedMiddleClickSVGAnchor); + assert_false(internals.isUseCounted(document, kSynthesizedMiddleClickSVGAnchor), "SVG anchor should not be counted initially"); + const event = new MouseEvent('click', { + button: 1 // Middle button + }); + link.dispatchEvent(event); + assert_true(internals.isUseCounted(document, kSynthesizedMiddleClickSVGAnchor), "SVG anchor should be counted after synthesized middle click"); + }, "Synthesized middle click on SVG anchor should trigger UseCounter"); + </script> +</body> +</html> \ No newline at end of file diff --git a/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-use-counter.html b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-use-counter.html new file mode 100644 index 0000000..cf05a372 --- /dev/null +++ b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-use-counter.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> + +<body> + <a id="link" href="#">Link</a> + <script> + const kSynthesizedMiddleClickAnchor = 5819; + + test(function () { + const link = document.getElementById('link'); + + internals.clearUseCounter(document, kSynthesizedMiddleClickAnchor); + assert_false(internals.isUseCounted(document, kSynthesizedMiddleClickAnchor), "Should not be counted initially"); + const event = new MouseEvent('click', { + button: 1 // Middle button + }); + link.dispatchEvent(event); + assert_true(internals.isUseCounted(document, kSynthesizedMiddleClickAnchor), "Should be counted after synthesized middle click"); + }, "Synthesized middle click on anchor should trigger UseCounter"); + + test(function () { + const link = document.getElementById('link'); + + internals.clearUseCounter(document, kSynthesizedMiddleClickAnchor); + const event = new MouseEvent('click', { + button: 0 // Left button + }); + link.dispatchEvent(event); + assert_false(internals.isUseCounted(document, kSynthesizedMiddleClickAnchor), "Should not be counted after synthesized left click"); + }, "Synthesized left click on anchor should not trigger UseCounter"); + </script> +</body> +</html> \ No newline at end of file diff --git a/tools/metrics/histograms/metadata/blink/enums.xml b/tools/metrics/histograms/metadata/blink/enums.xml index 1ec1baa..f1d550a 100644 --- a/tools/metrics/histograms/metadata/blink/enums.xml
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-area-use-counter.html b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-area-use-counter.html
new file mode 100644
index 0000000..d148cad
--- /dev/null
+++ b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-area-use-counter.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<body>
+ <map id="m" name="m">
+ <area href="" shape="default">
+ </map>
+ <img src="" usemap="#m" id="image">
+ <script>
+ const kSynthesizedMiddleClickArea = 5820;
+
+ test(function () {
+ const area = document.querySelector('area');
+
+ internals.clearUseCounter(document, kSynthesizedMiddleClickArea);
+ assert_false(internals.isUseCounted(document, kSynthesizedMiddleClickArea), "Area should not be counted initially");
+ const event = new MouseEvent('click', {
+ button: 1 // Middle button
+ });
+ area.dispatchEvent(event);
+ assert_true(internals.isUseCounted(document, kSynthesizedMiddleClickArea), "Area should be counted after synthesized middle click");
+ }, "Synthesized middle click on area should trigger UseCounter");
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-svg-anchor-use-counter.html b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-svg-anchor-use-counter.html
new file mode 100644
index 0000000..3596910
--- /dev/null
+++ b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-svg-anchor-use-counter.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<body>
+ <svg xmlns="http://www.w3.org/2000/svg">
+ <a href="" id="svglink"><text>link</text></a>
+ </svg>
+ <script>
+ const kSynthesizedMiddleClickSVGAnchor = 5821;
+
+ test(function () {
+ const link = document.getElementById('svglink');
+
+ internals.clearUseCounter(document, kSynthesizedMiddleClickSVGAnchor);
+ assert_false(internals.isUseCounted(document, kSynthesizedMiddleClickSVGAnchor), "SVG anchor should not be counted initially");
+ const event = new MouseEvent('click', {
+ button: 1 // Middle button
+ });
+ link.dispatchEvent(event);
+ assert_true(internals.isUseCounted(document, kSynthesizedMiddleClickSVGAnchor), "SVG anchor should be counted after synthesized middle click");
+ }, "Synthesized middle click on SVG anchor should trigger UseCounter");
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-use-counter.html b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-use-counter.html
new file mode 100644
index 0000000..cf05a372
--- /dev/null
+++ b/third_party/blink/web_tests/fast/events/pointerevents/synthesized-middle-click-use-counter.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<body>
+ <a id="link" href="#">Link</a>
+ <script>
+ const kSynthesizedMiddleClickAnchor = 5819;
+
+ test(function () {
+ const link = document.getElementById('link');
+
+ internals.clearUseCounter(document, kSynthesizedMiddleClickAnchor);
+ assert_false(internals.isUseCounted(document, kSynthesizedMiddleClickAnchor), "Should not be counted initially");
+ const event = new MouseEvent('click', {
+ button: 1 // Middle button
+ });
+ link.dispatchEvent(event);
+ assert_true(internals.isUseCounted(document, kSynthesizedMiddleClickAnchor), "Should be counted after synthesized middle click");
+ }, "Synthesized middle click on anchor should trigger UseCounter");
+
+ test(function () {
+ const link = document.getElementById('link');
+
+ internals.clearUseCounter(document, kSynthesizedMiddleClickAnchor);
+ const event = new MouseEvent('click', {
+ button: 0 // Left button
+ });
+ link.dispatchEvent(event);
+ assert_false(internals.isUseCounted(document, kSynthesizedMiddleClickAnchor), "Should not be counted after synthesized left click");
+ }, "Synthesized left click on anchor should not trigger UseCounter");
+ </script>
+</body>
+</html>
\ No newline at end of file
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