Medium CVSS 5.5 webkit Type Confusion 🔧 Commit mapped

Overview

Medium
Severity
5.5
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may lead to an unexpected process crash
ComponentJSC Wasm
Bug ClassType Confusion
Tracker276097
Fix commit2f5a0e40ca69 (WebKit/WebKit)
CVSS vectorCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
CISA KEVNot listed
CreditedGary Kwong
Disclosed2024-07-29

Background

ref.as_non_null
A WebAssembly typed-function-references instruction that converts a nullable reference into a non-nullable one, trapping if the value is null; it requires a reference-typed operand.
Typed function references
A Wasm proposal (gated by Options::useWasmTypedFunctionReferences) adding non-null and typed reference types, expanding the reference-type system beyond funcref/externref.
Wasm validation
The static type-checking pass over a module’s bytecode; a soundness gap here lets ill-typed operands reach compilation and execution.
isRefType
A predicate that returns whether a Wasm value type is a reference type, the exact check that was missing on the ref.as_non_null operand.
WASM_VALIDATOR_FAIL_IF
A macro that aborts validation with an error message when its condition holds, the mechanism used to reject the malformed instruction.

Root Cause Analysis

The patch adds a missing validation to the WebAssembly function parser/validator in Source/JavaScriptCore/wasm/WasmFunctionParser.h, in the handler for the ref.as_non_null instruction (part of the typed function references / GC proposal, gated by Options::useWasmTypedFunctionReferences). The handler pops one operand off the expression stack via WASM_TRY_POP_EXPRESSION_STACK_INTO(ref, …) and then calls addRefAsNonNull(ref, result), which is meant to take a nullable reference and produce its non-null form. The added line is WASM_VALIDATOR_FAIL_IF(!isRefType(ref.type()), "ref.as_non_null ref to type ", ref.type(), " expected a reference type"). The violated invariant is that ref.as_non_null must be applied only to a value of reference type; before the fix the parser accepted whatever type happened to be on top of the stack (e.g. a numeric type such as i32/i64/f32/f64/v128) and passed it to addRefAsNonNull, which assumes a reference operand. Feeding a non-reference value into reference-typed handling is a type confusion: downstream code (the compiler tiers and the runtime representation of the produced non-null reference) treats raw numeric bits as a pointer/reference, so the value’s type tag and its physical interpretation disagree. The added JSTests/wasm/stress/funcref-types.js ships a hand-crafted module that exercises this path (with the typed-function-references option enabled) and previously drove the engine into the unchecked ref.as_non_null, producing the unexpected process crash in the advisory.

The fix restores the invariant by making the validator reject any ref.as_non_null whose operand is not a reference type, failing module validation with a clear error before any code is generated or run.

Key insight
A missing isRefType operand check let ref.as_non_null accept non-reference values, creating an integer/reference type confusion in the Wasm engine; the fix is the classic add-the-validation restoration of the type invariant the compiler downstream assumed.

Attack Path

  1. Require the feature flag Target environments where useWasmTypedFunctionReferences is enabled (the test uses //@ requireOptions(’–useWasmTypedFunctionReferences=1’)); reachability depends on that option being on.
  2. Craft a malformed module From JavaScript, build a WebAssembly.Module whose bytecode contains a ref.as_non_null instruction whose operand on the value stack is a non-reference (numeric) type rather than a nullable reference.
  3. Slip past validation Before the fix the parser only popped the operand and did not check isRefType, so the malformed module validated successfully and was compiled.
  4. Trigger type confusion Instantiate and call the exported function; addRefAsNonNull and the compiled code treat the numeric operand as a reference, so raw bits are interpreted as a pointer/reference, corrupting the typed value.
  5. Crash (established) / escalate (background) The commit establishes an unexpected WebContent crash. Standard background: a controllable type confusion between an integer and a GC/function reference is a strong lever for a fake-object/arbitrary-read-write primitive, but this diff does not demonstrate that reliability.

Impact Assessment

The primitive is a validator type-confusion in the Wasm compiler: a non-reference (numeric) value is accepted where a reference is required, so the engine physically interprets attacker-supplied bits as a reference/pointer. Inference: such integer-to-reference confusions in a JIT are historically among the most powerful WebAssembly bugs and can be built toward arbitrary read/write and RCE inside the renderer, but this commit only establishes an unexpected crash and does not demonstrate a controllable primitive. The defect is confined to the WebContent (renderer) process executing the Wasm engine and remains behind the WebContent sandbox; reachability additionally requires the typed-function-references option to be enabled.

Changed Functions

FunctionChangeNotes
ref.as_non_null instruction handler (FunctionParser)
Source/JavaScriptCore/wasm/WasmFunctionParser.h
modified Adds WASM_VALIDATOR_FAIL_IF(!isRefType(ref.type()), ...) so ref.as_non_null rejects a non-reference operand before addRefAsNonNull runs, closing a validation gap that allowed type-confused input.
funcref-types stress test
JSTests/wasm/stress/funcref-types.js
added New regression test with a crafted module (typed function references enabled) that previously reached the unchecked ref.as_non_null path.

Audit Directions

  • Audit sibling reference instructions
    In WasmFunctionParser.h review every typed-reference / GC opcode handler (ref.as_non_null, ref.cast, ref.test, br_on_null, br_on_non_null, ref.func, struct/array.get/new) for a matching isRefType or exact-type check before the addToContext call; grep WASM_TRY_POP_EXPRESSION_STACK_INTO followed by addRef / addStruct* / addArray* with no WASM_VALIDATOR_FAIL_IF in between.
  • Grep for unchecked operand type use
    Search WasmFunctionParser.h for handlers that call ref.type() or pass a popped TypedExpression into a context method without first validating isRefType / the expected type, focusing on opcodes added with the typed-function-references and GC proposals.
  • Compare with the reference interpreter
    Cross-reference each reference-type opcode’s validation rules against the Wasm typed-references/GC spec to find any WebKit handler whose static checks are weaker than the spec mandates.
  • Fuzz under the feature flags
    Differentially fuzz WebKit Wasm validation with –useWasmTypedFunctionReferences=1 (and GC flags) using type-scrambled operands on reference opcodes to surface further accept-then-confuse gaps.

Original Bug Report

The reporter's bug is still restricted on the tracker.