A cached GPU object survives a redefine or reallocation
A cached render target, framebuffer attachment, descriptor pointer, or sub-allocation still points at backing storage that a redefine, reattach, or container growth has already freed or replaced — so its next use is a use-after-free or an uninitialized read.
Mechanism
GPU backends cache objects that point at backing storage: a Metal RenderTargetMtl, an FBO depth/stencil attachment, a wgpu::BindGroupLayoutEntry::nextInChain pointer, a Graphite buffer sub-allocation. A TexImage redefine, a layer-count increase, a mapping failure, or a growable container’s reallocation frees or replaces that storage.
If the cache is only set lazily (when its pointer is still null) or is never refreshed, the stale pointer survives the redefine. The next render, copy, or CreateBindGroupLayout then dereferences freed storage (use-after-free) or reads a newly-defined level that was never initialized (uninitialized-memory disclosure) — all in the GPU process, reachable from WebGL/WebGPU content.
Fix shape
if (!cached) lazy guard), use stable-address containers (SkTBlockList) for anything passed to the driver by address, and short-circuit teardown paths (reset()) when a mapping/allocation failure already invalidated the owner state.CVEs in this pattern
3 components · WebGL, ANGLE, Skia| CVE | What | Component | Vendor | Severity | Month | |
|---|---|---|---|---|---|---|
| CVE-2026-91720 | UninitializedMemory in ANGLE | ANGLE | chrome | High | 2026-09 | 🔧 |
| CVE-2026-84352 | UAF in WebGL | WebGL | chrome | Critical | 2026-09 | 🔧 |
| CVE-2026-87464 | UAF in WebGL | WebGL | chrome | Critical | 2026-09 | 🔧 |
| CVE-2026-19170 | UAF in WebGL | WebGL | chrome | Critical | 2026-08 | 🔧 |
| CVE-2026-19137 | UAF in WebGL | WebGL | chrome | Critical | 2026-08 | 🔧 |
| CVE-2026-17653 | UAF in Skia | Skia | chrome | Critical | 2026-07 | 🔧 |
| CVE-2026-13028 | UAF in WebGL | WebGL | chrome | Critical | 2026-06 | 🔧 |
| CVE-2026-13032 | UAF in WebGL | WebGL | chrome | Critical | 2026-06 | 🔧 |
| CVE-2026-14419 | UAF in Skia | Skia | chrome | Critical | 2026-06 | 🔧 |
| CVE-2026-13833 | UninitializedMemory in ANGLE | ANGLE | chrome | High | 2026-06 | 🔧 |
| CVE-2026-14385 | OOB in ANGLE | ANGLE | chrome | High | 2026-06 | 🔧 |
| CVE-2026-5868 | OOB in ANGLE | ANGLE | chrome | High | 2026-04 | 🔧 |
Hunt for siblings
Look for a cache that is populated only when its pointer is null (lazy init) but whose backing storage can be redefined, and for driver pointers stored in a growable container.
# Lazy-init cache that is never refreshed on redefine:
weggli --cpp '{
if (!$rt.getTexture()) { $rt.set($img, _); }
}'
# Pointer handed to the driver by address out of a growable container:
weggli --cpp '{ std::vector<_> $v; $chain.nextInChain = &$v[_]; }'
Mitigations that would catch this class
- Generation counters on GPU objects, checked before every cached-handle use
- Stable-address containers for pointers handed to the driver (never a growable vector)
- Fuzzing redefine/reattach/realloc sequences (TexImage after attach, layer-count change, map-fail)