Low watch CVSS 6.5 chrome Authorization Error 🔧 Commit mapped

Overview

Low
Severity
6.5
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactIncorrect authorization in Forms
DescriptionIncorrect authorization in Forms
ComponentForms
Bug ClassAuthorization Error
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker533075126
Fix commit451065790761 (chromium/src) +34/-1
CWECWE-863
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-07-09 (per vendor advisory)
Fix landed2026-07-19 (public git)
Disclosed2026-08-25
Patch gap37 days — fix public in source before the advisory

Background

`<label>` click forwarding
Clicking a <label> associated with a form control forwards focus/activation to the labeled control via HTMLLabelElement’s default event handling.
`FocusType`
A mojom::blink::FocusType enum (kMouse, kScript, etc.) that records how an element was focused; kMouse denotes a user-gesture-driven focus.
`WasLastFocusFromUserGesture()`
A per-element flag, derived from the FocusType, that downstream logic treats as evidence the focus resulted from genuine user interaction.
`Event::isTrusted()`
Returns whether an event was generated by the user agent (real user input) rather than synthesized by script (e.g. element.click()).

Root Cause Analysis

When a <label> forwarded a click to its control, HTMLLabelElement’s handler always called element->Focus(...) with a hard-coded mojom::blink::FocusType::kMouse, regardless of whether the originating click event was trusted. This meant a scripted label.click() — which dispatches an untrusted event — would focus the labeled input as if it were a real mouse interaction, causing WasLastFocusFromUserGesture() to return true without any user gesture. That violates the authorization invariant that user-gesture-gated focus state should only be set by trusted input.

The fix computes focus_type from evt.isTrusted(), using kMouse only for trusted events and kScript for untrusted ones, so scripted label clicks no longer masquerade as user-driven focus (confirmed by the test asserting EXPECT_FALSE(input1->WasLastFocusFromUserGesture()) after label1->click() and EXPECT_TRUE(...) after a kFromUserAgent simulated click).

Key insight
The single mistake was unconditionally labeling label-forwarded focus as kMouse; the fix selects kMouse vs kScript based on evt.isTrusted(), so only genuine user input sets WasLastFocusFromUserGesture().

Attack Path

  1. Place a label/control pair A page contains a <label for=input> bound to a target form control.
  2. Script the click Page JavaScript calls label.click(), dispatching an untrusted click event that reaches HTMLLabelElement’s default handler.
  3. Forge user-gesture focus Pre-patch, the handler focuses the control with FocusType::kMouse, so WasLastFocusFromUserGesture() becomes true even though no user interaction occurred.
  4. Bypass a gesture check Downstream behavior gated on user-gesture focus (e.g. autofill or other focus-privileged form behavior) is reached without a real gesture (inferred); the diff shows only the flag being incorrectly set, not the specific gated sink.

Impact Assessment

A malicious page’s script can set an input’s WasLastFocusFromUserGesture() flag without any user interaction, an incorrect-authorization issue in Blink’s Forms handling in the renderer process; the only precondition is a scriptable label/control pair. The advisory reports no exploited-in-the-wild status, and any concrete downstream abuse (such as autofill or navigation triggered by the forged gesture state) is (inferred) rather than demonstrated by the patch.

Changed Functions

FunctionChangeNotes
if
third_party/blink/renderer/core/html/forms/html_label_element.cc
modified
TEST_F
third_party/blink/renderer/core/html/forms/html_label_element_test.cc
modified

Files Changed

  • third_party/blink/renderer/core/html/forms/html_label_element_test.cc
  • third_party/blink/renderer/core/html/forms/html_label_element.cc

Audit Directions

  • Trusted-event gating on forwarded input
    Audit other places that re-dispatch or forward events (labels, custom controls, shadow DOM delegation) and pass a fixed user-gesture-implying FocusType/activation without consulting isTrusted().
  • Sources of `WasLastFocusFromUserGesture`
    Enumerate all callers of Element::Focus with FocusType::kMouse/other gesture types and verify each is reachable only from genuine user input.
  • Synthetic activation via `.click()`
    Look for behaviors gated on user-gesture/focus state that can be reached through scripted element.click() or DispatchSimulatedClick, which produce untrusted events.
From 451065790761eb16157922ddf51c9b581dcf5ed7 Mon Sep 17 00:00:00 2001
From: David Baron <[email protected]>
Date: Sun, 19 Jul 2026 06:47:30 -0700
Subject: [PATCH] Set FocusType more carefully when forwarding clicks from <label>.

Both the fix and the test are AI-authored, though from different AI
tools.  (I shortened a verbose code comment in the fix and reduced
overuse of the auto keyword in the test.)

Fixed: 533075126
Change-Id: I289f8f0d7c129776165ea6cfb502498c414cd706
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8115027
Reviewed-by: Mason Freed <[email protected]>
Commit-Queue: David Baron <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1664455}
---
diff --git a/third_party/blink/renderer/core/html/forms/html_label_element.cc b/third_party/blink/renderer/core/html/forms/html_label_element.cc
index a5a5d07..d1064db 100644
--- a/third_party/blink/renderer/core/html/forms/html_label_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_label_element.cc
@@ -260,8 +260,13 @@
       // In case of double click or triple click, selection will be there,
       // so do not focus the control element.
       if (!is_label_text_selected) {
+        // Set focus_type so that label.click() from script can't set
+        // WasLastFocusFromUserGesture.
+        const mojom::blink::FocusType focus_type =
+            evt.isTrusted() ? mojom::blink::FocusType::kMouse
+                            : mojom::blink::FocusType::kScript;
         element->Focus(FocusParams(SelectionBehaviorOnFocus::kRestore,
-                                   mojom::blink::FocusType::kMouse, nullptr,
+                                   focus_type, nullptr,
                                    FocusOptions::Create()));
       }
     }
diff --git a/third_party/blink/renderer/core/html/forms/html_label_element_test.cc b/third_party/blink/renderer/core/html/forms/html_label_element_test.cc
index 8565b7da..575f982a 100644
--- a/third_party/blink/renderer/core/html/forms/html_label_element_test.cc
+++ b/third_party/blink/renderer/core/html/forms/html_label_element_test.cc
@@ -6,6 +6,7 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 
 namespace blink {
@@ -74,4 +75,31 @@
   EXPECT_EQ("", label->TextContentExcludingLabelable().StripWhiteSpace());
 }
 
+TEST_F(HTMLLabelElementTest, WasLastFocusFromUserGesture) {
+  SetBodyInnerHTML(R"HTML(
+    <label id=label1 for=input1></label>
+    <input id=input1>
+    <label id=label2 for=input2></label>
+    <input id=input2>
+  )HTML");
+  HTMLLabelElement* label1 = To<HTMLLabelElement>(
+      GetDocument().getElementById(AtomicString("label1")));
+  Element* input1 = GetDocument().getElementById(AtomicString("input1"));
+  Element* label2 = GetDocument().getElementById(AtomicString("label2"));
+  Element* input2 = GetDocument().getElementById(AtomicString("input2"));
+
+  // Untrusted click (such as label.click() from script) should not set
+  // WasLastFocusFromUserGesture().
+  label1->click();
+  EXPECT_EQ(input1, GetDocument().FocusedElement());
+  EXPECT_FALSE(input1->WasLastFocusFromUserGesture());
+
+  // Trusted click (such as user interaction) should set
+  // WasLastFocusFromUserGesture().
+  label2->DispatchSimulatedClick(nullptr,
+                                 SimulatedClickCreationScope::kFromUserAgent);
+  EXPECT_EQ(input2, GetDocument().FocusedElement());
+  EXPECT_TRUE(input2->WasLastFocusFromUserGesture());
+}
+
 }  // namespace blink
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/blink/renderer/core/html/forms/html_label_element_test.cc b/third_party/blink/renderer/core/html/forms/html_label_element_test.cc
index 8565b7da..575f982a 100644
--- a/third_party/blink/renderer/core/html/forms/html_label_element_test.cc
+++ b/third_party/blink/renderer/core/html/forms/html_label_element_test.cc
@@ -6,6 +6,7 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 
 namespace blink {
@@ -74,4 +75,31 @@
   EXPECT_EQ("", label->TextContentExcludingLabelable().StripWhiteSpace());
 }
 
+TEST_F(HTMLLabelElementTest, WasLastFocusFromUserGesture) {
+  SetBodyInnerHTML(R"HTML(
+    <label id=label1 for=input1></label>
+    <input id=input1>
+    <label id=label2 for=input2></label>
+    <input id=input2>
+  )HTML");
+  HTMLLabelElement* label1 = To<HTMLLabelElement>(
+      GetDocument().getElementById(AtomicString("label1")));
+  Element* input1 = GetDocument().getElementById(AtomicString("input1"));
+  Element* label2 = GetDocument().getElementById(AtomicString("label2"));
+  Element* input2 = GetDocument().getElementById(AtomicString("input2"));
+
+  // Untrusted click (such as label.click() from script) should not set
+  // WasLastFocusFromUserGesture().
+  label1->click();
+  EXPECT_EQ(input1, GetDocument().FocusedElement());
+  EXPECT_FALSE(input1->WasLastFocusFromUserGesture());
+
+  // Trusted click (such as user interaction) should set
+  // WasLastFocusFromUserGesture().
+  label2->DispatchSimulatedClick(nullptr,
+                                 SimulatedClickCreationScope::kFromUserAgent);
+  EXPECT_EQ(input2, GetDocument().FocusedElement());
+  EXPECT_TRUE(input2->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.