WebGL capability vector (limits + extensions) differs between the main thread and a Worker OffscreenCanvas
br.webgl_caps_worker_vs_main · convicts
What it catches
The HARDENED complement of br.webgl_worker_vs_main. That rule compares the renderer STRING across realms; a spoofer that learns of it can cheaply patch the UNMASKED_RENDERER into Worker scope too (one value) and defeat it while keeping the renderer matched. This rule compares the high-entropy CAPABILITY VECTOR — MAX_TEXTURE_SIZE, MAX_RENDERBUFFER_SIZE, MAX_VIEWPORT_DIMS, the uniform/varying/attrib limits, MAX_COMBINED_TEXTURE_IMAGE_UNITS, and the supported-extension count — computed identically (gl.getContext('webgl')) in the main realm and a Worker OffscreenCanvas. One physical GPU yields one limit set, so a real browser matches in both realms; a main-realm WebGL fake that matched the renderer string but did not reproduce the whole limit vector inside the Worker diverges here. Grounded headful (2026-06-27): a real (SwiftShader) Chromium reports an identical caps digest in both realms (no fire), while a main+worker renderer-string spoof that leaks the real Worker limits fires webgl_caps_worker_divergence. EXPERIMENTAL on the same caveat as br.webgl_worker_vs_main: grounded only on software rendering here — a real-hardware browser whose Worker OffscreenCanvas software-falls-back could diverge legitimately, so it stays for review until validated against a Tier-3 real-GPU device.
Signals it reads
browser.webgl_caps_worker_divergence
How it fires
present
Evaders it caught 1
Bypassed by 10
Frontier evaders that reach the detector uncaught (scored only suspicious, defeating every convicting tell) — this check is not one that stops them. The red-team frontier this detection still has to convict.