Chrome 148's switch to the host libm turned Math.tanh into an OS fingerprint
Original source
Since Chromium 148, Math.tanh is now fingerprintable to link underlying OS
Hacker News →IEEE 754 pins down how a double is stored but never requires transcendental functions like sin, cos, or tanh to be correctly rounded, so every platform’s math library approximates them slightly differently. glibc on Linux, Apple’s libsystem_m on macOS, and Windows’ UCRT disagree on a meaningful fraction of inputs — often by a single unit in the last place. That means the last bits of a number a browser computes quietly encode the operating system that produced them. The classic example is Math.tanh(0.8), which returns three distinct bit patterns across genuine Linux, macOS, and Windows Chrome, giving anti-bot systems a per-OS signature that needs no math to read, just a lookup table.
The leak is new. Through Chrome 147, V8 computed tanh with a bundled fdlibm port that produced identical bits everywhere; a V8 commit shipped in 14.8.57 (Chrome 148) swapped it for the platform std::tanh, which reads the host libm. Crucially, tanh is the only JavaScript Math.* that leaks — everything else is statically linked in V8 and identical across systems, so naively spoofing the rest introduces detectable inconsistencies. The exposure is broader than JS math, though: CSS trig functions call the host libm directly through Blink (with degree-to-radian reduction that must be reproduced bit-for-bit), and Web Audio on macOS touches three separate libraries at once — Apple’s Accelerate for FFT and vector DSP, scalar libsystem_m for the compressor’s per-sample transcendentals. Architecture adds another axis, since ARM and x86 differ on fused-multiply-add and NaN sign handling.
For tools like Scrapfly that must present a browser matching a real one across hundreds of signals, closing this is hard. Adding noise fails twice: the value matches no real OS, and per-call randomness is itself a tell. The only durable fix is exact algorithmic reproduction — recovering a target libm’s minimax coefficients, exponent tables, and reduction constants, transcribing them verbatim as hex-encoded doubles in portable C, matching even the inputs where the reference rounds the wrong way, and compiling with FMA contraction disabled so the compiler can’t invent or drop fusions. The upshot for defenders and fingerprinting researchers alike: sub-ULP floating-point behavior is now a stable, hard-to-forge tracking surface, and User-Agent claims can be contradicted by a single well-chosen math call.
Read the full article
Continue reading at Hacker News →This is an AI-generated summary. Read the original for the full story.