the clear path and the shader path paint opaque red to the same bytes
A fixed-function clear to red and a shader emitting red read back as byte-for-byte identical pixels.
What a detector infers
Opaque red can be produced two ways: the fixed-function clear path, and a fragment shader emitting vec4(1,0,0,1). Both end in the same framebuffer and are read back through the same readPixels call, so on real hardware they are byte-for-byte identical. That identity is the invariant.
A spoof that farbles WebGL readback to fake a GPU perturbs the value it reads without matching what a second, independent render path produces, and a software rasteriser can round the float-to-UNORM8 conversion differently on the clear fast-path than on the shader path — either way the two reads diverge.
The clear path is used as a gate, not merely a step: if clearing to (1,0,0,1) does not read back as exactly opaque red, this backend colourspace or conversion is unfamiliar and the check goes quiet rather than guessing. That gate is also what makes it robust to the browsers that would otherwise burn it.
Brave farbles WebGL readback and Firefox with resistFingerprinting blanks it, but both do so as a deterministic function of origin and pixel index, so identical input buffers read through identical calls receive identical treatment and the comparison still holds. Only a genuine divergence between two paths into one framebuffer fails it.
How to resolve it
Both paths write the same colour to the same framebuffer and are read through the same call, so they cannot differ on real hardware. Perturbing WebGL readback to fake a GPU, or a software rasteriser rounding the two paths differently, is what separates them. Leave the render path native, or present a GPU whose driver produces a consistent framebuffer.
Read in the wild by
CloakBrowser issues
The tracker records WebGL readback that is perturbed or rounded inconsistently between render paths when a GPU is spoofed or a software fallback is used.
CloakHQ/CloakBrowser #31, #33 (WebGL readPixels stability)
CloakHQ/CloakBrowser#31Every attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Render & GPU
- the GPU named by the renderer string can actually render
webgl-performance-caveat-vs-renderergetContext("webgl", {failIfMajorPerformanceCaveat: true}) asks Chromium for a context only if it can supply one without a major performance… - ANGLE's translated shader is written in the dialect the renderer string implies
shader-backend-vs-rendererThe UNMASKED_RENDERER_WEBGL string is a label — a piece of text a page can rewrite to name any GPU and any graphics backend. - every extension WebGL advertises can actually be instantiated
webgl-extensions-vs-drivergetSupportedExtensions() returns a list a page can rewrite; getExtension(name) either hands back a real extension object or null, and that… - every advertised WebGL extension carries a registry name
webgl-extension-names-conformA deployed commercial agent packs the supported-extension list into a bitmap against an ordered list of names it already knows — and carries… - a mediump claim of fp32 precision is delivered by the arithmetic
shader-mediump-claim-vs-arithmeticgetShaderPrecisionFormat is a claim about float precision; a shader that computes a value only fp32 can represent is the GPU keeping or… - silence renders as exact zero through the Web Audio graph
audio-render-silence-integrityThe other audio checks compare two renders of a sound; this one renders silence and asserts it stayed silent, which catches a different kind… - a constant signal renders at exactly the amplitude it was given
audio-render-dc-integrityThe companion to the silence check below, and the input that one structurally cannot see. - the same audio render reproduces itself
audio-render-reproducibilityAn OfflineAudioContext render involves no output device and no clock.
Clearcote is a browser built for fingerprint coherence
It is a Chromium fork, maintained by the same people who wrote this reference. It ships as a compiled browser rather than as a stealth script injected into someone else's — which is a description of how it is built, and is not an argument about how it behaves on this check.
This audit takes no position on how Clearcote scores on Render & GPU checks, on this one, or anywhere else. It has no baseline corpus of other people's fingerprints to rank you against and no vendor scoreboard — nearly every check is self-referential, asking one browser the same question through two independent APIs and reporting whether both answers can be true at once. It runs identically on any browser, including ours. Run it on yours and read the result yourself.
See the other checks in Render & GPU — the family webgl-draw-path-invariance belongs to.
