← Chrome — 2026-W37

550f34cd989f500105792f10bcde754ecad1467f  Incorrect cast to CSSSuperellipseValue

severity low class TypeConfusion CVSS 6.5 signal score 3.8 third_party/blink/renderer/core/ patch-now AI review CONFIRMED
Structural signals: area:third_party/blink/renderer/core/ (+2.5), surgical (+1.3)

The bug at a glance

An unchecked downcast Tocssvalue::CSSSuperellipseValue was performed on a shape CSSValue that could instead be a plain identifier, so in release builds Param() is read off an object of the wrong type, producing a type confusion that at minimum crashes the renderer. Reachability is via ordinary CSS corner-shape serialization, making it web-content-triggerable but confined to the renderer with limited primitive strength.

A page sets a ‘corner’ CSS value whose shape is a non-‘round’ identifier (e.g. ’notch’, ‘bevel’) and then forces serialization/getComputedStyle; the mismatched To<> cast treats the identifier object as a CSSSuperellipseValue and dereferences the wrong vtable/fields, crashing or confusing types in the Blink renderer.

Root cause

SerializeCornerValue’s helper assumed the shape CSSValue was always a CSSSuperellipseValue and used the checked-in-debug/unchecked-in-release To<> downcast before calling .Param(). But the shape can legitimately be a CSSIdentifierValue (notch/bevel/etc.), so To<> casts an unrelated object type and Param() reads memory as if it were a CSSSuperellipseValue. The fix replaces To<> with DynamicTo<>, returning false when the object is not actually a CSSSuperellipseValue.

Key code

Checked DynamicTo<> replaces unchecked To<> downcast

if (const auto* super_ellipse =
        DynamicTo<cssvalue::CSSSuperellipseValue>(shape)) {
  const CSSPrimitiveValue& param = super_ellipse->Param();
  ...
}
return false;

Patch walkthrough

  • third_party/blink/renderer/core/css/style_property_serializer.cc — Replaces the unconditional Tocssvalue::CSSSuperellipseValue(shape) cast with a DynamicTo<> guarded block and a false fallback, so a non-superellipse shape value no longer causes a bad-cast dereference during corner-shape serialization.
  • third_party/blink/web_tests/external/wpt/css/css-borders/corner-shape/corner-computed.html — Adds computed-value tests (e.g. ‘0px notch’, ‘0px superellipse(1)’) that exercise shape values that previously hit the wrong cast path.
  • third_party/blink/web_tests/external/wpt/css/css-borders/corner-shape/corner-valid.html — Adds valid-value tests for ‘0px notch’/‘0px round’/‘0px superellipse(1)’ to lock in the corrected handling.

Background

CSSSuperellipseValue — Blink CSSValue subclass representing the superellipse() corner-shape function with a numeric Param().

To<> vs DynamicTo<> — To<> is an unchecked downcast (SECURITY_DCHECK only), while DynamicTo<> returns nullptr when the runtime type does not match.

corner-shape serialization — style_property_serializer.cc converts computed corner/corner-shape values back to CSS text for getComputedStyle and cssText.

Vulnerability window

  1. Reachability — Attacker page sets a ‘corner’ property whose shape resolves to a non-superellipse identifier such as notch or bevel.
  2. Trigger — Serialization (getComputedStyle/cssText) invokes the helper that casts the shape value with To.
  3. Primitive — Param() is read off an object of the wrong type, a type-confusion read (inferred to manifest as a crash in release).
  4. Escalation — Beyond a renderer crash, exploitation would require the confused layout to yield a controllable read/write primitive (inferred, not demonstrated).

Proof of concept

Conceptually: in a page, set an element’s ‘corner’ shape to a non-‘round’ keyword like notch (e.g. corner value ‘0px notch’), then call getComputedStyle(el).corner or read cssText to force the serializer down the incorrect-cast path. No exploit code is provided.

Exploitation

  1. Setup — Define CSS corner-shape using an identifier shape distinct from superellipse/round.
  2. Trigger — Force serialization via getComputedStyle or cssText access (inferred).
  3. Confusion — To<> treats the identifier value as CSSSuperellipseValue and reads Param() (inferred).

Detection & hunting

For defenders and detection engineers:

  • grep for Tocssvalue::CSSSuperellipseValue or To<…Value> in serializer/style code — Flag unchecked To<> downcasts of polymorphic CSSValue objects not preceded by an IsX()/type guard.
  • crash reports with __cxa_bad_cast or SECURITY_DCHECK in style_property_serializer — Hunt renderer crashes during getComputedStyle on corner-shape properties.

Audit directions

  • Other corner/corner-shape and shape-function serializers in style_property_serializer.cc — Audit for To<> casts on shape CSSValues that assume a single concrete subtype.
  • All Tocssvalue::*Value downcasts across Blink CSS code — Convert to DynamicTo<> where the value’s runtime type is attacker-influenced.

Before / after

Loading diff…