← Chrome — 2026-W37

627c7dc35ba395df3ed86ad662ba56f8111f3bbb  [Blink] Fetch ClientSharedImage early in CreateExternalTexture

severity low class DoS CVSS 4.3 signal score 5 third_party/blink/renderer/modules/ AI review CONFIRMED
Structural signals: null_guard (+1.2), area:third_party/blink/renderer/modules/ (+2.5), surgical (+1.3)

The bug at a glance

On GPU context loss, lease->GetSharedImage() can return null, and the draw path dereferenced it unchecked (shared_image->size()), a null-pointer dereference that crashes the renderer. Impact is limited to a renderer-process crash with no shown memory-corruption primitive, and triggering it depends on racing a GPU context loss.

An attacker who can induce GPU context loss (e.g. heavy WebGPU/video workload or a reset) while a video frame is imported via WebGPU importExternalTexture can turn the resulting null SharedImage into a renderer crash.

Root cause

CreateExternalTexture() acquired a WebGpuSharedImageLease but only fetched lease->GetSharedImage() at the end. The copy path guarded with IsGpuContextLost(), but the draw path dereferenced lease->GetSharedImage()->size() directly; if context loss made GetSharedImage() return null, this was a null-pointer dereference. The fix fetches shared_image once immediately after acquiring the lease and returns {} if it is null, and adds a post-operation null recheck to catch context loss during the copy/draw.

Key code

Early fetch and null-check of leased SharedImage

scoped_refptr<gpu::ClientSharedImage> shared_image = lease->GetSharedImage();
if (!shared_image) {
  return {};
}
...
params.dest_rect = gfx::RectF(shared_image->size());

Patch walkthrough

  • third_party/blink/renderer/modules/webgpu/external_texture_helper.cc — Fetches lease->GetSharedImage() once right after acquiring the lease and bails on null, removes the outer IsGpuContextLost() guard from the copy path (now redundant), uses the non-null local in both copy and draw paths, and rechecks GetSharedImage() after the operation to detect context loss mid-copy/draw.
  • third_party/blink/renderer/platform/graphics/gpu/webgpu_shared_image_cache.h — Moves WebGpuSharedImageLease::IsGpuContextLost() back to private since callers no longer need the explicit guard, reducing the API surface.

Background

CreateExternalTexture — Blink WebGPU helper that imports a media/video frame into a GPUExternalTexture backed by a leased SharedImage.

WebGpuSharedImageLease — RAII handle over a GPU SharedImage whose GetSharedImage() can become null after GPU context loss.

GPU context loss — A GPU process/context reset invalidates backing resources, causing accessors to return null mid-operation.

Vulnerability window

  1. Reachability — Web content imports a video frame into WebGPU via importExternalTexture, reaching CreateExternalTexture().
  2. Trigger — GPU context loss occurs so lease->GetSharedImage() returns null while the draw path proceeds.
  3. Primitive — The draw path dereferences the null SharedImage (shared_image->size()), crashing the renderer (inferred as a null-deref DoS).
  4. Escalation — No escalation beyond crash is evident from the diff.

Proof of concept

Conceptually: on a WebGPU device, repeatedly call device.importExternalTexture with a video frame while concurrently forcing GPU context loss (heavy allocation/reset). If the loss lands after the lease is acquired but the draw path reads the SharedImage, GetSharedImage() returns null and is dereferenced. No exploit code provided; this is a crash, not a corruption primitive.

Exploitation

  1. Setup — Create a WebGPU device and a video source for external-texture import.
  2. Trigger — Induce GPU context loss concurrent with importExternalTexture (inferred timing dependence).
  3. Crash — Null SharedImage dereference in the draw path crashes the renderer (inferred).

Detection & hunting

For defenders and detection engineers:

  • grep for lease->GetSharedImage()-> or GetSharedImage()->size() without a prior null check — Flag SharedImage accessors dereferenced without null handling across GPU context-loss boundaries.
  • renderer null-deref crash stacks in external_texture_helper.cc — Correlate crashes with GPU context-loss events during WebGPU external texture import.

Audit directions

  • Other WebGPU/canvas paths using WebGpuSharedImageLease or ClientSharedImage after possible context loss — Ensure GetSharedImage() results are null-checked before and after GPU operations.
  • Media PaintCanvasVideoRenderer copy/draw integrations — Audit for unchecked SharedImage dereferences on the draw/paint branch.

Before / after

Loading diff…