550f34cd989f500105792f10bcde754ecad1467f Incorrect cast to CSSSuperellipseValue
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
- Reachability — Attacker page sets a ‘corner’ property whose shape resolves to a non-superellipse identifier such as notch or bevel.
- Trigger — Serialization (getComputedStyle/cssText) invokes the helper that casts the shape value with To.
- Primitive — Param() is read off an object of the wrong type, a type-confusion read (inferred to manifest as a crash in release).
- 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
- Setup — Define CSS corner-shape using an identifier shape distinct from superellipse/round.
- Trigger — Force serialization via getComputedStyle or cssText access (inferred).
- 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.