Your Browser Does Math Differently on Every OS, and Anti-Bot Systems Read the Bits
Engineering-Artikel, veröffentlicht am **12. Juli 2026** von **Scrapfly Engineering**, über einen wenig bekannten Browser-*Fingerprinting*-Kanal: **die letzten Bits einer Gleitkommazahl verraten das Betriebssystem**. **Der Mechanismus**: IEEE 754 legt fest, wie ein `double` gespeichert wird, verlangt aber **nicht**, dass `sin`, `cos`, `tanh` oder `exp` korrekt gerundet werden; jedes System liefert daher eine eigene **libm**, die einen Bruchteil eines ULP gegen Geschwindigkeit eintauscht, mit eigenen Minimax-Koeffizienten, Tabellen und Reduktionskonstanten. Dadurch liefert `Math.tanh(0.8)` **drei unterschiedliche Werte**, je nach glibc (Linux), libsystem_m (macOS) und UCRT (Windows) — „ein einziger tanh-Aufruf mit dem richtigen Eingabewert ist eine Signatur pro Betriebssystem. Wer macOS behauptet, aber Linux-Rechenbits zurückgibt, widerspricht dem eigenen User-Agent.“ **Das Erkennungsmerkmal ist neu und lässt sich genau datieren**: bis **Chrome 147** berechnete V8 `tanh` mit einem eingebetteten **fdlibm**-Port, überall identisch und ohne jedes Leck; der V8-Commit `c1486295ae5` ersetzte ihn durch `std::tanh`, ausgeliefert in V8 14.8.57, also **Chrome 148** — 148, 149 und 150 lecken, 147 und früher nicht. **Drei Oberflächen bündeln die Lecks**: `Math.tanh` (die **einzige** betroffene `Math.*`-Funktion, da V8 alle übrigen einbettet und statisch verlinkt), **sämtliche CSS-Trigonometriefunktionen** (Blink ruft direkt die libm des Hosts auf, nach einer gradbasierten Winkelreduktion, die keinen Code mit `Math.sin` teilt), und **Web Audio** (wo der Kompressor bei skalarer libsystem_m bleibt, während FFT- und Vektorstufen über **Accelerate** laufen). **Vier Fallen** erschweren die Gegenmaßnahme: Nur manche Funktionen lecken — daher **erzeugt das Fälschen der übrigen eine erkennbare Inkonsistenz**; JavaScript und CSS sind getrennte Codepfade; **macOS enthält zwei Mathematikbibliotheken, die voneinander abweichen** (skalar vs. Accelerate, je nach Funktion bei 10 bis 89 % der Eingabewerte: `cos(0)` liefert auf der einen Seite `1.0`, auf der anderen `0.9999999999999999`); und **auch die Architektur leckt** (FMA und die Vorzeichenweitergabe bei NaN unterscheiden sich zwischen ARM und x86). **Die verworfene und die gewählte Gegenmaßnahme**: Rauschen hinzuzufügen scheitert zweifach — der Wert stimmt mit **keinem** realen Betriebssystem überein, und die fehlende Determinismus pro Aufruf ist selbst ein Erkennungsmerkmal. Der einzige Weg ist die **bitgenaue Reproduktion**: die Koeffizienten der Ziel-libm extrahieren, sie **hexadezimal** transkribieren (eine dezimale Transkription würde anders runden), jede fused multiply-add-Operation explizit als `fma()` schreiben und mit `-ffp-contract=off` kompilieren, damit der Compiler keine davon erfindet oder wegoptimiert. **Bemerkenswerter Hinweis**: Der Herausgeber stellt vorab klar, dass „die Beiträge hier mit KI verfasst werden“, während Mechanismen, Zahlen und Code aus eigener Feder stammen.
**Scrapfly Engineering** — équipe d'ingénierie de **Scrapfly** · fournisseur d'infrastructure de collecte web. Le texte annonce sa position d'intérêt sans détour : *« Scrapfly ships a browser that has to match a real one across hundreds of signals · and math is one of the harder ones. »* On lit donc un **attaquant du problème de détection** · qui documente le canal parce qu'il doit le neutraliser.