[3] WebGL GPU-process draft-extension setting unenforced across IPC
Rated Medium because the diff closes an IPC trust-boundary gap that allowed any WebContent process to opt into draft-quality ANGLE extensions inside the GPU process regardless of the WebGLDraftExtensionsEnabled setting. There is no direct memory primitive; the impact is broadened reachable code in a more privileged process that becomes available to a follow-on exploit chain.
The patch adds a new supportWebGLDraftExtensions boolean to GraphicsContextGLAttributes (declared in the header, serialized in WebGL.serialization.in). WebGLRenderingContextBase::resolveGraphicsContextGLAttributes populates it from scriptExecutionContext.settingsValues().webGLDraftExtensionsEnabled. In the GPU process, GPUConnectionToWebProcess::createGraphicsContextGL rejects the IPC via MESSAGE_CHECK when the WebContent-supplied attribute is true while the trusted shared preference is false. To make the check meaningful, UnifiedWebPreferences.yaml adds sharedPreferenceForWebProcess: true to WebGLDraftExtensionsEnabled. Inside GraphicsContextGLANGLE::initialize, the requestable-extension filter now skips GCGLExtension::ANGLE_base_vertex_base_instance unless attributes.supportWebGLDraftExtensions is true.
Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp
Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp
Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp
Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml
Patch Details
The change spans four cooperating files: a new attribute on the IPC-serialized struct, a settings read at WebContent-side context creation, a MESSAGE_CHECK at the GPU-process IPC entry, and an extension-filter branch in the ANGLE init path. The YAML change ensures the trusted preference value reaches m_sharedPreferencesForWebProcess so the IPC validator has something to compare against. Existing code paths are not restructured; the patch is an additive cross-process plumbing of one boolean.
Security-relevant setting (draft-extension gate) not plumbed into the GPU-process context-creation IPC, leaving the trusted preference unenforced across the process boundary.
Background
The GPU process is a separate sandboxed process that hosts WebGL/WebGPU on behalf of WebContent; RemoteGraphicsContextGL in WebContent forwards WebGL calls over IPC to a GraphicsContextGLANGLE in the GPU process. ANGLE is the OpenGL-ES-on-top-of-platform-GL translation layer that backs WebKit's WebGL implementation and exposes its own set of GL_ANGLE_* and GL_EXT_* extensions, some of which are draft (subject to spec change, less hardened).
ANGLE returns a list of extensions that can be enabled at runtime (GL_REQUESTABLE_EXTENSIONS_ANGLE); WebKit copies this into m_allRequestableExtensions and then filters to m_requestableExtensions — only entries in the filtered set can be activated by getExtension. MESSAGE_CHECK is a WebKit IPC validator macro that terminates the connection if the assertion fails, used at trust boundaries to reject malformed or attacker-controlled values from a less-trusted process. sharedPreferenceForWebProcess: true in UnifiedWebPreferences.yaml causes a preference value to be replicated from the UI process into the GPU process's m_sharedPreferencesForWebProcess, giving the GPU process a trusted copy independent of WebContent.
Attack surface
This change narrows attack surface. Before the fix, ANGLE_base_vertex_base_instance was reachable from any WebContent process through enableExtension/getExtension paths regardless of the WebGLDraftExtensionsEnabled setting. The newly-introduced MESSAGE_CHECK enforces that draft-extension exposure is reachable only when the trusted shared preference agrees, closing the IPC path that previously let WebContent unilaterally opt in.
Analysis
Pre-fix, GraphicsContextGLANGLE::initialize populated m_requestableExtensions from ANGLE's full requestable-extensions string without filtering against the WebGLDraftExtensionsEnabled setting. The setting existed, but no piece of state plumbed it into GraphicsContextGLAttributes, so the GPU-process-side context creation had nothing to gate on. Any WebContent process — including a compromised one — could obtain access to draft-quality ANGLE extensions regardless of policy.
This is the recurring "preference enforced only on the WebContent side" pattern. Many WebKit features have a setting that gates exposure but only the WebContent side consults it; the GPU/Networking process trusts the attribute struct that crosses the boundary. The mitigation pattern used here — sharedPreferenceForWebProcess: true plus a MESSAGE_CHECK against the trusted copy at the IPC entry point — is a clean template that should be replicated for any other "draft / experimental / privileged" WebGL/WebGPU/Media feature gates.
This is not directly exploitable as a standalone memory-corruption primitive. The relevant scenario is a chain: an attacker first achieves arbitrary script execution or limited renderer-side compromise, then uses the unfiltered IPC to make the GPU process expose ANGLE_base_vertex_base_instance, then attacks bugs reachable only when that draft extension is active. Pre-fix the IPC accepted any caller; post-fix the MESSAGE_CHECK rejects connections that request draft-extension support when the trusted preference is off, so the attacker would need to either flip the preference (a different boundary) or find a separate path to those code paths. Lockdown Mode is already independently enforced by the existing MESSAGE_CHECK(!isLockdownModeEnabled()) and is unaffected by this change.
This vulnerability weakens the GPU-process trust boundary against a (compromised) WebContent process. The security model assumes that draft, less-mature ANGLE extensions are gated behind an explicit setting because their command pipelines have less hardening / fuzzing maturity than non-draft extensions. Pre-fix that gate did not exist at the IPC layer: any WebContent could request ANGLE_base_vertex_base_instance and exercise its draw commands inside the GPU process. An attacker who plausibly gains script execution in WebContent could reach draft-extension code paths in ANGLE and the platform GL driver, broadening the surface available for a GPU-process compromise / sandbox escape chain.
Audit directions
-
Settings that gate exposure of an experimental feature consulted only in WebContent. Audit every IPC entry in
GPUConnectionToWebProcessandRemoteGraphicsContextGL/RemoteGPUfor parameters that mirror a WebCore preference but are not re-validated againstm_sharedPreferencesForWebProcess. Start by greppingMESSAGE_CHECKinSource/WebKit/GPUProcess/and cross-referencing eachSettings/preference name inUnifiedWebPreferences.yamlthat lackssharedPreferenceForWebProcess: true. -
WebGL/WebGPU extension and feature lists computed from device/driver-reported strings without filtering against the experimental-feature gate. Audit
GraphicsContextGLANGLE::initializeand the WebGPU adapter feature enumeration for other entries in the requestable-extensions array that are "draft" upstream but currently unfiltered. Verify each draftGCGLExtensionenum value has a corresponding gate in the filter loop that just got introduced forANGLE_base_vertex_base_instance. -
Shared preferences synchronized into the GPU/Networking process can drift from WebContent's view. Investigate the update sequencing of
m_sharedPreferencesForWebProcessinGPUConnectionToWebProcessversuscreateGraphicsContextGLto ensure preference toggles apply before any in-flight context-creation IPC is processed; a staletruecould permit creation right before the gate is observed asfalse. -
Parameter validation inside
ANGLE_base_vertex_base_instanceitself. Confirm whether negative or huge values are clamped before reaching the platform GL driver; the fact that this extension was singled out for gating suggests its validation surface is actively considered untrusted.
Note: The pre-fix reachability of
ANGLE_base_vertex_base_instancefrom any WebContent regardless ofWebGLDraftExtensionsEnabled, the broader claim that draft extensions are less hardened than non-draft ones, and the speculation about am_sharedPreferencesForWebProcessupdate race are inferences from the diff shape rather than directly demonstrated. The structural change — preference plumbed across the IPC +MESSAGE_CHECKagainst a trusted copy + extension filter — is fully visible in the patch.