Released November 5, 2025

CVE-2025-43511

CVSS 6.5 severity medium CWE-416 vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H

Overview

Impact:

Description: Processing maliciously crafted web content may lead to an unexpected process crash

Researchers: 이동하 (Lee Dong Ha of BoB 14th)

Key insight. The inspector animation table stored animations by raw pointer (and dereferenced a possibly-null script-execution context), so a destroyed animation left a dangling entry; switching to WeakRef and null-checking the context restores lifetime safety.

Patch Details

diff --git a/Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp b/Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp
index 299fa548e71e..1399bcebf310 100644
--- a/Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp
@@ -362,7 +362,11 @@ Inspector::Protocol::ErrorStringOr<Ref<Inspector::Protocol::Runtime::RemoteObjec
     if (!animation)
         return makeUnexpected(errorString);
 
-    auto* state = animation->protectedScriptExecutionContext()->globalObject();
+    RefPtr scriptExecutionContext = animation->scriptExecutionContext();
+    if (!scriptExecutionContext)
+        return makeUnexpected("Animation is detached from context"_s);
+
+    auto* state = scriptExecutionContext->globalObject();
     auto injectedScript = m_injectedScriptManager.injectedScriptFor(state);
     ASSERT(!injectedScript.hasNoValue());
 
@@ -588,7 +592,7 @@ void InspectorAnimationAgent::frameNavigated(LocalFrame& frame)
 String InspectorAnimationAgent::findAnimationId(WebAnimation& animation)
 {
     for (auto& [animationId, existingAnimation] : m_animationIdMap) {
-        if (existingAnimation == &animation)
+        if (existingAnimation.ptr() == &animation)
             return animationId;
     }
     return nullString();
@@ -605,7 +609,7 @@ WebAnimation* InspectorAnimationAgent::assertAnimation(Inspector::Protocol::Erro
 void InspectorAnimationAgent::bindAnimation(WebAnimation& animation, RefPtr<Inspector::Protocol::Console::StackTrace> backtrace)
 {
     auto animationId = makeString("animation:"_s, IdentifiersFactory::createIdentifier());
-    m_animationIdMap.set(animationId, &animation);
+    m_animationIdMap.set(animationId, animation);
 
     auto animationPayload = Inspector::Protocol::Animation::Animation::create()
         .setAnimationId(animationId)
diff --git a/Source/WebCore/inspector/agents/InspectorAnimationAgent.h b/Source/WebCore/inspector/agents/InspectorAnimationAgent.h
index 1c5b538fe4d3..5eb7009f0189 100644
--- a/Source/WebCore/inspector/agents/InspectorAnimationAgent.h
+++ b/Source/WebCore/inspector/agents/InspectorAnimationAgent.h
@@ -100,7 +100,7 @@ private:
     Inspector::InjectedScriptManager& m_injectedScriptManager;
     WeakRef<Page> m_inspectedPage;
 
-    MemoryCompactRobinHoodHashMap<Inspector::Protocol::Animation::AnimationId, WebAnimation*> m_animationIdMap;
+    HashMap<Inspector::Protocol::Animation::AnimationId, WeakRef<WebAnimation, WeakPtrImplWithEventTargetData>> m_animationIdMap;
 
     WeakHashMap<WebAnimation, Ref<Inspector::Protocol::Console::StackTrace>, WeakPtrImplWithEventTargetData> m_animationsPendingBinding;
     Timer m_animationBindingTimer;

Background

Advisory: Apple Security Advisory

Attribute Value
CVE CVE-2025-43511
Bugzilla 300926
Component WebCore
Bug Class UAF
Severity medium
Commit bb6619c2421179b0…
Advisory Apple Advisory

Terminology

  • Web Inspector agent — Backend objects (here InspectorAnimationAgent) that service the inspector frontend’s protocol domains and hold references to inspected page objects.
  • Raw pointer vs WeakRef — A raw T* is not lifetime-aware and dangles when the object dies; a WeakRef auto-nulls, so lookups can detect a dead object.
  • WebAnimation / scriptExecutionContext — A Web Animations object bound to a document/worker context that can become detached (context null) during teardown or navigation.
  • Detached animation — An animation whose scriptExecutionContext has gone away, so its global object is unavailable.

Root Cause Analysis

The Web Inspector animation agent tracked live animations in m_animationIdMap, a map from an inspector animation-id string to a raw WebAnimation*. Nothing kept those pointers in sync with object lifetime: when a WebAnimation was destroyed, its entry remained as a dangling raw pointer. Subsequent agent operations dereferenced it — findAnimationId compared each stored raw pointer to a live animation, and resolveAnimation did animation->protectedScriptExecutionContext()->globalObject() — yielding a use-after-free. resolveAnimation had a second defect: protectedScriptExecutionContext() can return null for an animation detached from its context, and the code dereferenced it unconditionally (a null/недействительный access). The fix changes m_animationIdMap to hold WeakRef<WebAnimation> values (which automatically drop when the animation dies, so lookups never see a stale pointer — findAnimationId now compares existingAnimation.ptr()), and bindAnimation stores the animation by weak reference. resolveAnimation now takes RefPtr scriptExecutionContext = animation->scriptExecutionContext() and returns an error (‘Animation is detached from context’) when it is null instead of dereferencing it. The restored invariant is that the inspector’s animation table observes animations weakly and validates liveness/context before use. This path is only reachable while a Web Inspector session is attached and driving the Animation domain.

Attack Path

1. Attach the inspector

An active Web Inspector session enables the Animation agent, which binds animations into m_animationIdMap by raw pointer.

2. Create and destroy an animation

Page script creates a Web Animation that the agent binds, then drops all references so the WebAnimation is collected, leaving a dangling raw pointer in the map.

3. Trigger a lookup

Invoke an agent operation (resolve/findAnimationId) that iterates or dereferences the stored pointer, or resolve an animation whose scriptExecutionContext is null.

4. Use-after-free / null deref

The agent dereferences the freed WebAnimation (or the null context), crashing or corrupting memory in WebContent.

Impact Assessment

A use-after-free (plus a null-context dereference) of a WebAnimation held by raw pointer in the inspector animation table, in the WebContent process. It is only reachable while a Web Inspector session is attached and exercising the Animation domain, which sharply limits real-world exploitability from a plain web page; the realistic outcome is a crash, with UAF-to-corruption possible under inspector-driven conditions. Rated medium.

Audit Directions

Other raw-pointer maps in inspector agents

grep Source/WebCore/inspector/agents for HashMap/Vector values typed as bare * (e.g. Node*, WebAnimation*) that outlive the pointee; prefer WeakRef/WeakHashMap.

Unchecked protected*() dereferences

grep for protectedScriptExecutionContext()-> and similar protected accessors dereferenced without a null check across WebCore.

Other id-to-object registries

Audit inspector domains (DOM, Canvas, Animation) that map protocol ids to engine objects for the same raw-pointer lifetime gap.

Changed Functions

Function File Change Note
InspectorAnimationAgent::resolveAnimation Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp modified Takes scriptExecutionContext() into a RefPtr and returns an error when null instead of calling protectedScriptExecutionContext()->globalObject() unconditionally.
InspectorAnimationAgent::findAnimationId Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp modified Compares existingAnimation.ptr() now that map values are WeakRef rather than raw pointers.
InspectorAnimationAgent::bindAnimation Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp modified Stores the animation as a weak reference (m_animationIdMap.set(id, animation)) instead of &animation.
m_animationIdMap Source/WebCore/inspector/agents/InspectorAnimationAgent.h modified Changed from a map to WebAnimation* to a HashMap of WeakRef<WebAnimation, WeakPtrImplWithEventTargetData>, so entries auto-drop on destruction.

Files Changed

Source Files

  • Source/WebCore/inspector/agents/InspectorAnimationAgent.cpp
  • Source/WebCore/inspector/agents/InspectorAnimationAgent.h