CVE-2026-43735
Overview
Background
- Same-Origin Policy (SOP)
- The core web isolation rule preventing one origin from reading another origin’s content without permission (CORS).
- Origin taint
- Media loaded cross-origin without CORS is ’tainted’; the pixels may be displayed but must not be read back. Canvas enforces this by throwing on getImageData().
- importExternalTexture
- A WebGPU API that ingests an HTMLVideoElement’s frames as a texture usable in shaders — a path that, if unchecked, lets shader output be read back to script.
Root Cause Analysis
This fixes a cross-origin data leak in WebGPU’s importExternalTexture.
Before the fix, GPUDevice::importExternalTexture accepted an HTMLVideoElement source without checking whether the video is origin-tainted (cross-origin without CORS). A page could therefore import a cross-origin, CORS-tainted video as a WebGPU external texture, sample it in a shader, and read the result back through a GPU buffer — exfiltrating pixels of a cross-origin video that the Same-Origin Policy is meant to keep unreadable (the same protection canvas enforces by throwing on getImageData for tainted content).
The fix threads the ScriptExecutionContext into importExternalTexture ([CallWith=CurrentScriptExecutionContext] in the IDL, new parameter in the .h/.cpp) and, before importing, checks (*videoElement)->taintsOrigin(context.securityOrigin()); if the video would taint the caller’s origin it returns a SecurityError (‘Cross origin external videos are not allowed in WebGPU’) instead of importing.
The restored invariant is that only same-origin (or CORS-approved) video pixels can enter the WebGPU pipeline, matching canvas taint rules. The layout test confirms importExternalTexture throws SecurityError for a cross-origin tainted video. Established by the diff.
Attack Path
- Load a cross-origin video without CORS The page creates a <video> whose src is a cross-origin URL and no crossorigin attribute, so it becomes origin-tainted.
- Import it as a WebGPU external texture Pre-patch, device.importExternalTexture({source: video}) accepts the tainted video with no origin check.
- Sample and read back the pixels A compute/render shader samples the external texture and writes results to a GPU buffer the page can map and read.
- Exfiltrate cross-origin video content The page reads back pixel-derived data from the cross-origin video, defeating the Same-Origin Policy (now blocked with a SecurityError).
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
GPUDevice::importExternalTextureSource/WebCore/Modules/WebGPU/GPUDevice.cpp |
modified | Takes a ScriptExecutionContext and rejects the import with a SecurityError when the source video taintsOrigin(context.securityOrigin()), preventing cross-origin tainted video from entering WebGPU. |
GPUDevice::importExternalTexture (declaration)Source/WebCore/Modules/WebGPU/GPUDevice.h |
modified | Signature adds the ScriptExecutionContext& parameter. |
GPUDevice.importExternalTexture (IDL)Source/WebCore/Modules/WebGPU/GPUDevice.idl |
modified | Adds [CallWith=CurrentScriptExecutionContext] so the caller's execution context (and thus security origin) is available for the taint check. |
Files Changed
LayoutTests/http/tests/webgpu/import-external-texture-cross-origin-video-expected.txtLayoutTests/http/tests/webgpu/import-external-texture-cross-origin-video.htmlSource/WebCore/Modules/WebGPU/GPUDevice.cppSource/WebCore/Modules/WebGPU/GPUDevice.hSource/WebCore/Modules/WebGPU/GPUDevice.idl
Audit Directions
- New media-ingestion APIs vs. taintAudit every WebGPU/WebGL entry point that accepts an HTMLVideoElement, HTMLImageElement, or canvas for a taintsOrigin() check equivalent to canvas’s; new GPU surfaces are the likeliest to miss it.
- Origin plumbingVerify IDL methods that need the caller origin actually receive the execution context (e.g. [CallWith=CurrentScriptExecutionContext]) rather than inferring same-origin.