← Chrome — 2026-W37

9456bac0b659b5bfc11e423626848fe5d5505e5c  Restrict EventTrigger target to Node.

severity low class TypeConfusion CVSS 5.3 signal score 3.8 third_party/blink/renderer/core/ AI review PLAUSIBLE
Structural signals: area:third_party/blink/renderer/core/ (+2.5), surgical (+1.3)

The bug at a glance

The commit (marked Fixed: with a tracked bug) tightens the EventTrigger animation API’s target type from the broad EventTarget base to the narrower Node, which strongly implies downstream code assumed a Node and could be fed a non-Node EventTarget (e.g. window, XHR, MessagePort) causing a type-confusion / invalid-cast condition; medium rather than high because no explicit memory-corruption primitive is shown in the diff.

An attacker scripting the Web Animations EventTrigger could previously supply any EventTarget (not just a DOM Node) as eventTarget; if listener-attachment or invocation logic treats the stored target as a Node, this is a confusable-type path a defender should treat as a potential UAF/corruption precursor.

Root cause

EventTrigger stored its target as WeakMember and accepted/exposed EventTarget via the constructor, eventTarget() getter, IDL attribute, and EventTriggerOptions dictionary. The patch narrows all of these to Node (adding the node.h include and forward declaration). The IDL change makes Blink’s bindings reject non-Node values at the API boundary, and the internal member is now a WeakMember, eliminating the possibility that non-Node EventTargets reach code paths that assume a Node. The pre-patch over-broad type is the root cause of the (inferred) type-confusion.

Key code

Target type narrowed from EventTarget to Node

-  EventTrigger(String event_type, EventTarget& event_target);
+  EventTrigger(String event_type, Node& event_target);
...
-  WeakMember<EventTarget> event_target_;
+  WeakMember<Node> event_target_;

Patch walkthrough

  • third_party/blink/renderer/core/animation/event_trigger.h — Changes constructor param, eventTarget() return type, and the stored WeakMember from EventTarget to Node, and swaps the forward declaration; this removes the ability to hold a non-Node target that downstream code might mis-handle.
  • third_party/blink/renderer/core/animation/event_trigger.cc — Updates the constructor signature to take Node& and includes node.h; constrains construction to Node targets.
  • third_party/blink/renderer/core/animation/event_trigger.idl — Changes the readonly eventTarget attribute from EventTarget to Node so the bindings layer enforces the narrower type on the web-exposed getter.
  • third_party/blink/renderer/core/animation/event_trigger_options.idl — Changes the EventTriggerOptions.eventTarget dictionary member from EventTarget to Node, so a page can no longer pass arbitrary EventTargets (window, XHR, etc.) when constructing an EventTrigger.

Background

EventTrigger — A Web Animations AnimationTrigger that starts/controls an animation in response to an event dispatched to a target.

EventTarget vs Node — EventTarget is the base interface for anything receiving events (Window, XMLHttpRequest, MessagePort, etc.); Node is the narrower DOM-tree interface, so EventTarget is a strict superset.

WeakMember — Oilpan weak reference that is nulled when the referent is collected, used here for the trigger’s target.

Vulnerability window

  1. Reachability — Web content constructs an EventTrigger via the Web Animations API and, pre-patch, could pass any EventTarget as eventTarget.
  2. Trigger — A non-Node EventTarget is stored in event_target_ where downstream listener-attachment/invocation logic expects a Node (inferred).
  3. Primitive — Node-assuming code operating on a non-Node object yields a type-confusion / invalid cast (inferred, not shown in diff).
  4. Escalation — Any resulting memory-safety consequence would require the mishandling code path, which is not included in this diff (inferred).

Proof of concept

Conceptually, a page would construct an EventTrigger (via the Web Animations trigger API) passing eventTarget set to a non-Node EventTarget such as window or an XMLHttpRequest, then exercise whatever flow attaches listeners or invokes on the stored target; the fix now rejects non-Node values at the bindings layer. No exploit code is provided.

Exploitation

  1. Setup — Script instantiates an EventTrigger with a non-Node eventTarget via EventTriggerOptions (inferred).
  2. Confusion — Internal code that assumes event_target_ is a Node dereferences/casts it incorrectly (inferred).

Detection & hunting

For defenders and detection engineers:

  • weggli/grep for IDL attributes or members typed ‘EventTarget’ later consumed as Node (static_cast<Node> / To)* — Hunt for API surfaces that accept the broad EventTarget type but internally treat targets as DOM Nodes.

Audit directions

  • other AnimationTrigger / Web Animations APIs taking EventTarget — Review any animation or observer API whose IDL exposes EventTarget while implementation assumes a Node or Element for the same confusable-type risk.

Before / after

Loading diff…