Article URL: https://scrapfly.dev/posts/browser-math-os-fingerprint/ Comments URL: https://news.ycombinator.com/item?id=48884853 Points: 88 # Comments: 28

Math.tanh, every CSS trig function, and the Web Audio compressor all route through the host libm, so the rounding of a cosine betrays the OS a browser actually runs on. Where the leak lives across V8, Blink, and Web Audio, and what bit-for-bit reproduction of Apple's math library takes to close it. Fingerprinting is usually about canvas, WebGL, fonts, audio. There is a quieter signal, and it lives in the last bits of a number. That is not a constant. It is an approximation, and the exact bits depend on the OS that computed it. A genuine Mac runs Math.tanh through Apple’s math library. Linux runs it through glibc1. The two disagree on about a quarter of all inputs, usually by one unit in the last place (1 ULP2). Windows, through the Universal C Runtime, disagrees with both on a few percent, and on the input above all three land on a different bit. Measured over the DevTools protocol on Chrome 150: Linux (glibc), macOS 26 on Apple Silicon (libsystem_m), Windows 11 (ucrtbase.dll). tanh(0.5) is one of the roughly three-in-four inputs where everyone agrees, which is exactly why it makes a useless probe. tanh(0.8) is one that separates all three at once. One tanh call on the right input is a per-OS signature. Claim macOS, return Linux math bits, and you have contradicted your own User-Agent. This tell is recent. Until Chrome 148, V8 computed tanh itself with a bundled fdlibm3 port, so it returned the same bits on every OS and leaked nothing. V8 commit c1486295ae5 replaced it with std::tanh, which reads the host libm. It first shipped in V8 14.8.57, which is Chrome 148. Chrome 147 and earlier do not leak here. Chrome 148, 149, and 150 do. Scrapfly ships a browser that has to match a real one across hundreds of signals. Math is one of the harder ones. Here is why, and how we close it. IEEE 7544 defines how a double is stored. It does not require sin, cos, tanh, or exp to be correctly rounded. Correct rounding is expensive, so every vendor ships a libm5 that trades a fraction of a ULP for speed, with its own minimax6 coefficients, lookup tables, and reduction constants.