CVE-2025-24201
Overview
Impact:
Description: Maliciously crafted web content may be able to break out of Web Content sandbox. This is a supplementary fix for an attack that was blocked in iOS 17.2. (Apple is aware of a report that this issue may have been exploited in an extremely sophisticated attack against specific targeted individuals on versions of iOS before iOS 17.2.)
Researchers: Apple
Key insight. WebGL enable/disable forwarded PRIMITIVE_RESTART_FIXED_INDEX — a capability the implementation must manage per WebGL version — straight to GL, letting content desynchronize primitive-restart state into an out-of-bounds condition; rejecting the toggle restores control to the implementation.
Patch Details
diff --git a/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp b/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp
index 55f23b3eb337..bbe382cf413d 100644
--- a/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp
+++ b/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp
@@ -1187,7 +1187,11 @@ void GraphicsContextGLANGLE::disable(GCGLenum cap)
{
if (!makeContextCurrent())
return;
-
+ if (cap == PRIMITIVE_RESTART_FIXED_INDEX) {
+ if (m_isForWebGL2)
+ addError(GCGLErrorCode::InvalidOperation);
+ return;
+ }
GL_Disable(cap);
}
@@ -1221,7 +1225,11 @@ void GraphicsContextGLANGLE::enable(GCGLenum cap)
{
if (!makeContextCurrent())
return;
-
+ if (cap == PRIMITIVE_RESTART_FIXED_INDEX) {
+ if (!m_isForWebGL2)
+ addError(GCGLErrorCode::InvalidOperation);
+ return;
+ }
GL_Enable(cap);
}
Background
Advisory: Apple Security Advisory
| Attribute | Value |
|---|---|
| CVE | CVE-2025-24201 |
| Bugzilla | 285858 |
| Component | WebKit |
| Bug Class | OOB |
| Severity | medium |
| Commit | 7d784721e440d049… |
| Advisory | Apple Advisory |
Terminology
- ANGLE — WebKit’s translation layer running WebGL on native GPU APIs; its Metal backend executes in the GPU/WebContent graphics path.
- PRIMITIVE_RESTART_FIXED_INDEX — A GL capability controlling primitive-restart in indexed draws; in WebGL2 it is implicitly always on and not app-toggleable, and absent in WebGL1.
- WebGL enable/disable — APIs that set GL capabilities; forwarding an implementation-managed capability from untrusted content desynchronizes GL state.
Root Cause Analysis
This is a supplementary fix (exploited in the wild before iOS 17.2) for an out-of-bounds sandbox escape via WebGL primitive-restart state in the ANGLE Metal backend. WebGL exposes enable(cap)/disable(cap); GraphicsContextGLANGLE::enable/disable forwarded the capability straight to GL_Enable/GL_Disable. PRIMITIVE_RESTART_FIXED_INDEX must not be toggled by web content: in WebGL2 it is always enabled and managed by the implementation, and in WebGL1 it does not exist. Allowing content to enable or disable it drove ANGLE/GL into an inconsistent primitive-restart configuration that, combined with index buffers during geometry processing, produced out-of-bounds memory access in the GPU pipeline — a corruption primitive used to break out of the WebContent sandbox. The fix special-cases the capability: disable(PRIMITIVE_RESTART_FIXED_INDEX) raises InvalidOperation in WebGL2 and returns without forwarding to GL; enable(PRIMITIVE_RESTART_FIXED_INDEX) raises InvalidOperation when NOT in WebGL2 and returns. The restored invariant is that primitive-restart state is controlled by the implementation per WebGL version, never by untrusted enable/disable calls.
Attack Path
1. Create a WebGL context
Open a WebGL1 or WebGL2 context from web content.
2. Toggle the forbidden capability
Call gl.enable/gl.disable(PRIMITIVE_RESTART_FIXED_INDEX), which pre-patch forwarded straight to ANGLE/GL.
3. Desynchronize primitive-restart state
Combined with crafted index buffers, the inconsistent state drives out-of-bounds access in the GPU geometry pipeline.
4. Escape the sandbox
Leverage the OOB corruption to break out of the WebContent sandbox (observed in a sophisticated in-the-wild attack).
Impact Assessment
An out-of-bounds memory-corruption primitive reachable from ordinary WebGL content that was used to escape the WebContent sandbox — the advisory notes exploitation in an extremely sophisticated targeted attack and frames it as a supplementary fix. Despite the ‘medium’ label the real-world impact is sandbox escape, among the most serious outcomes for renderer-reachable bugs.
Audit Directions
Other implementation-managed capabilities
Audit GraphicsContextGLANGLE::enable/disable and cap-forwarding for other GL capabilities that WebGL1/WebGL2 must manage internally rather than accept from content.
WebGL version gating
Grep for m_isForWebGL2 checks around GL state to find capabilities/queries valid in only one WebGL version that are not gated.
Changed Functions
| Function | File | Change | Note |
|---|---|---|---|
GraphicsContextGLANGLE::disable |
Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp |
modified | For PRIMITIVE_RESTART_FIXED_INDEX raises InvalidOperation in WebGL2 and returns without forwarding to GL_Disable. |
GraphicsContextGLANGLE::enable |
Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp |
modified | For PRIMITIVE_RESTART_FIXED_INDEX raises InvalidOperation when not WebGL2 and returns without forwarding to GL_Enable. |