Medium CVSS 4.3 webkit UAF 🔧 Commit mapped

Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may lead to an unexpected Safari crash
ComponentJSC Bytecode
Bug ClassUAF
Tracker317142
Fix commit7920db18a51b (WebKit/WebKit) +41/-3
CWECWE-20, CWE-703 (Improper input validation)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L
CISA KEVNot listed
CreditedOpenAI Codex Security - Amy Burnett
Disclosed2026-08-17

Background

Polymorphic call inline cache
A CallLinkInfo-backed cache for call sites that see multiple callees; linkPolymorphicCall updates it.
virtualForWithFunction / host call
Resolves a callee; for a host InternalFunction it may perform a call that runs JS, which can reset/free the inline cache.
CallLinkInfo lifetime
Compiled call-site metadata that JS run during resolution can invalidate/free, making later use a UAF.

Root Cause Analysis

This fixes a use-after-free of a CallLinkInfo when a polymorphic call resolves to a host (InternalFunction) callee that runs JavaScript. operationPolymorphicCall (JIT) and llint_polymorphic_call (LLInt) call virtualForWithFunction to resolve the callee, then link the polymorphic inline cache: linkPolymorphicCall(vm, owner, calleeFrame, *callLinkInfo, CallVariant(calleeAsFunctionCell)). For a host InternalFunction callee, virtualForWithFunction performs a host call that can execute arbitrary JavaScript; that JS can reset/free the inline cache, invalidating *callLinkInfo.

Pre-patch, virtualForWithFunction returned with calleeAsFunctionCell left null for the InternalFunction case, and the callers unconditionally called linkPolymorphicCall using the now-possibly-freed *callLinkInfo — a use-after-free.

The fix has two parts: virtualForWithFunction now sets calleeAsFunctionCell = internalFunction for the InternalFunction path (dynamicDowncast<InternalFunction>), and both callers only call linkPolymorphicCall when calleeAsFunctionCell is non-null, with the comment that a null cell means virtualForWithFunction did a host call that ran JS and may have freed *callLinkInfo, so it must not link.

The restored invariant is that the polymorphic call is only linked when the CallLinkInfo is still valid — never after a host call that could have freed it. The regression test installs a Proxy whose apply handler deletes the getter (resetting the IC) during a polymorphic getter call.

Key insight
A polymorphic call was linked using *callLinkInfo even after virtualForWithFunction made a host call that ran JS and could free it; only linking when the callee cell is non-null (and setting it for InternalFunction) closes the UAF.

Attack Path

  1. Build a polymorphic call site Run JS so a call/getter site becomes polymorphic and uses operationPolymorphicCall / llint_polymorphic_call with a CallLinkInfo.
  2. Route to a host callee Make the callee a host InternalFunction (e.g. a Proxy apply) so virtualForWithFunction performs a host call that runs JS.
  3. Free the CallLinkInfo From that JS (the Proxy apply handler), delete the property/reset the inline cache so *callLinkInfo is freed.
  4. Use-after-free The caller links the polymorphic call using the freed CallLinkInfo, corrupting/crashing the WebContent process.

Impact Assessment

A use-after-free in the WebContent process reachable from ordinary polymorphic calls that reach a host callee running attacker JS. Freeing and reusing the CallLinkInfo under attacker control is a groomable primitive; the advisory rates it a crash, but JSC inline-cache UAFs commonly escalate toward memory corruption and code execution.

Changed Functions

FunctionChangeNotes
operationPolymorphicCall
Source/JavaScriptCore/jit/JITOperations.cpp
modified Only calls linkPolymorphicCall when calleeAsFunctionCell is non-null, since a null cell means virtualForWithFunction ran a host call that may have freed *callLinkInfo.
llint_polymorphic_call
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
modified Same guard: skip linkPolymorphicCall on a null callee cell to avoid using a freed CallLinkInfo.
virtualForWithFunction
Source/JavaScriptCore/bytecode/RepatchInlines.h
modified Sets calleeAsFunctionCell to the InternalFunction (dynamicDowncast) so the callers can distinguish the host-call path that may have freed the CallLinkInfo.

Files Changed

  • JSTests/stress/operation-polymorphic-call-host-call-ic-reset.js
  • Source/JavaScriptCore/bytecode/RepatchInlines.h
  • Source/JavaScriptCore/jit/JITOperations.cpp
  • Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

Audit Directions

  • Post-host-call IC use
    Audit operationPolymorphicCall/virtual call slow paths for uses of *callLinkInfo (or other IC state) after a step that can run JS and reset the cache.
  • Null-cell contract
    Grep virtualForWithFunction callers to confirm they treat a null calleeAsFunctionCell as ‘do not link’, not as a benign case.

Original Bug Report

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