High-end mobile GPU string but MAX_TEXTURE_SIZE below the 16384 mobile floor
br.mobile_gpu_caps_mismatch · convicts
What it catches
The MOBILE analog of br.webgl_renderer_caps_mismatch (which patterns ONLY desktop high-end GPUs: RTX/Radeon RX 6000+/Apple M/Intel Arc) — the gap that check leaves on the mobile axis. A recent-FLAGSHIP mobile GPU exposes MAX_TEXTURE_SIZE, MAX_RENDERBUFFER_SIZE AND MAX_VIEWPORT_DIMS all 16384; a renderer STRING naming one where ANY of that cap triad is < 16384 is spoofed over a lesser/SwiftShader (8192) backend. FP-SAFETY SCOPING (v2, 2026-07-02): the pattern is CONSERVATIVELY limited to GPUs CONFIDENTLY 16384 — Adreno 7xx/8xx (SD 8-Gen-1+ flagship), Mali-G76-79 + G710-719, Immortalis. MID-RANGE Adreno 6xx (610/618/619/620 — including the Pixel 5's Adreno 620) are DELIBERATELY EXCLUDED: their MAX_TEXTURE_SIZE is NOT confidently 16384 (may be 8192; unverified via WebSearch + driver-variant per the sources), so flagging them would FALSE-FIRE on real mid-range phones. The excluded cases are fully backstopped by br.mobile_gpu_uniforms_software (SwiftShader's vu 4096 fires under ANY mobile GPU string) + br.webgl_maxtexture_unallocatable, so the narrowing loses NO net coverage while removing the FP risk. Checking all THREE (not just maxTexture) closes the both-realm fork that fakes ONLY maxTexture in both realms — evading the maxTexture arm AND br.webgl_caps_worker_divergence (the digests stay consistent) — yet leaves the renderbuffer/viewport at the real 8192. This is the SOURCE-LEVEL-FORK case that slips past EVERY other mobile GPU rung: br.mobile_gpu_not_mobile passes (the string IS a mobile GPU family), br.webgl_software passes (the string is not software), and a BOTH-realm fork (patching the renderer in main AND worker) evades br.webgl_worker_divergence — yet the silicon's limit vector cannot be string-patched in any realm. CONVICTING (w0.7): the claimed mobile GPU contradicts the hardware it runs on. FP-SAFE: real high-end mobile GPUs are >=16384 (universal on Adreno 6xx+/modern Mali); an honest lesser mobile GPU carries a lesser renderer string (Adreno 3xx/4xx, Mali-T) OUT of the high-end pattern, and an honest software renderer names itself (caught by webgl_software). GROUNDED LIVE: SPOOF_UA=<a Pixel mobile UA> + KS_RENDERER='ANGLE (Qualcomm, Adreno (TM) 730, OpenGL ES 3.2)' (a high-end mobile GPU string over the SwiftShader 8192 backend) FIRES mobile_gpu_caps_mismatch while mobile_gpu_not_mobile AND webgl_software both stay SILENT — catching the mobile-GPU source-fork none of the other rungs see; KS_DEVICE='Pixel 5' (honest SwiftShader string) does NOT fire it (out of the high-end mobile pattern, correctly caught by mobile_gpu_not_mobile instead). Reopened the axis after a premature two-dry close: the mobile GPU-caps surface was still open.
Signals it reads
browser.mobile_gpu_caps_mismatch
How it fires
present
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.