Artikel von Scrapfly Engineering (12. Juli 2026) über einen Fingerprinting-Kanal, der in den letzten Bits einer Zahl sitzt.
Der Mechanismus. IEEE 754 legt fest, wie ein double gespeichert wird, verlangt aber nicht die korrekte Rundung transzendenter Funktionen. Da korrekte Rundung teuer ist, liefert jede Plattform eine eigene libm mit eigenen Minimax-Koeffizienten, Tabellen und Konstanten. Dadurch liefert Math.tanh(0.8) drei unterschiedliche Werte, je nach glibc, libsystem_m und UCRT. Linux und macOS weichen bei rund einem Viertel der Eingabewerte voneinander ab, typischerweise um 1 ULP. „Ein Detektor braucht keine Mathematik, nur eine Tabelle.“ Und die Inkonsistenz ist unmittelbar ausnutzbar: macOS zu behaupten, aber Linux-Bits zurückzugeben, widerspricht dem eigenen User-Agent.
Das Erkennungsmerkmal ist neu und datiert. Bis Chrome 147 berechnete V8 tanh mit einem eingebetteten fdlibm, überall identisch. Der Commit c1486295ae5 ersetzte ihn durch std::tanh, das die libm des Hosts liest, ausgeliefert mit Chrome 148.
Drei Oberflächen lecken.Math.tanh ist die einzige betroffene Math.*-Funktion — V8 bettet alle übrigen ein und verlinkt sie statisch. Alle sieben CSS-Trigonometriefunktionen lecken, wobei Blink die libm des Hosts nach einer gradbasierten Winkelreduktion aufruft, die keinen Code mit Math.sin teilt. Und Web Audio berührt drei Bibliotheken innerhalb eines einzigen Graphen: Accelerate für FFT- und Vektorstufen, skalare libsystem_m für die transzendenten Funktionen des Kompressors. WASM dagegen leckt nicht das Betriebssystem — nur die Architektur.
Vier Fallen erschweren die Gegenmaßnahme: Nur manche Funktionen lecken, sodass das Fälschen der übrigen eine erkennbare Asymmetrie erzeugt; JavaScript und CSS sind getrennte Codepfade; macOS enthält zwei Mathematikbibliotheken, die voneinander abweichen, je nach Funktion um 10 bis 89 %, sodass „Apples Mathematik nachbilden“ erst dann Sinn ergibt, wenn klar ist, welche an welcher Stelle aufgerufen wird; und ARM und x86 unterscheiden sich bei fused multiply-add und der NaN-Weitergabe.
Rauschen funktioniert nicht: Es erzeugt einen Wert, der mit keinem realen Betriebssystem übereinstimmt, und sein fehlender Determinismus ist selbst ein Signal. Der einzige Weg ist die bitgenaue Reproduktion — Koeffizienten aus der Ziel-libm extrahiert und hexadezimal transkribiert, jede Fusion als explizites fma() geschrieben, kompiliert mit -ffp-contract=off.
Der Herausgeber gibt an, dass seine Beiträge mit KI-Unterstützung verfasst werden, während Mechanismen, Zahlen und Code aus eigener Feder stammen.
Kernpunkte
Das Prinzip, in einem Satz. IEEE 754 schreibt die Speicherung eines double vor, nicht die korrekte Rundung transzendenter Funktionen. Korrekte Rundung ist teuer, daher liefert jedes System seine eigene libm mit eigenen Minimax-Koeffizienten, Tabellen und Reduktionskonstanten. Der Rundungsunterschied ist eine Signatur.
Die Sonde, die man kennen sollte.Math.tanh(0.8) liefert 0.6640367702678491 unter Linux (glibc), 0.664036770267849 unter macOS (libsystem_m) und 0.6640367702678489 unter Windows (UCRT) — alle drei unterscheiden sich, um 2 ULP. Linux und macOS weichen bei rund einem Viertel aller Eingabewerte voneinander ab, typischerweise um 1 ULP; Windows weicht bei einigen Prozent von beiden ab. → „Ein Detektor braucht keine Mathematik, nur eine Tabelle.“
Das Erkennungsmerkmal ist bis auf den Commit genau datiert, und genau das macht den Artikel nützlich. bis Chrome 147 berechnete V8 tanh mit einem eingebetteten fdlibm-Port — überall dieselben Bits, kein Leck. Der V8-Commit c1486295ae5 ersetzte ihn durch std::tanh, das die libm des Hosts liest; ausgeliefert in V8 14.8.57 = Chrome 148. 148, 149, 150 lecken. 147 und früher nicht. → Eine Datenschutzregression, ausgelöst durch eine unspektakuläre Implementierungsentscheidung, und ein präzises Versionsfenster, um einen Fingerabdruck zu datieren.
Die Leck-Übersicht — der am besten wiederverwendbare Teil. | Operation | Math. (JS) | CSS calc() | Web Audio | |---|---|---|---| | sin cos tan | in V8 eingebettet | libm des Hosts | Accelerate (FFT), skalar im Kompressor | | asin acos atan atan2 | in V8 eingebettet | libm des Hosts | nicht verwendet | | tanh | libm des Hosts | — | nicht verwendet | | exp, log, pow | in V8 eingebettet | libm des Hosts | skalar im Kompressor | | Vektor, FFT | — | — | Accelerate (vDSP) auf dem Mac | | sqrt, Arithmetik | Hardware | Hardware | Hardware | → V8 leitet fast alles über seine eigene eingebettete Mathematik: JavaScript leckt nur an einer einzigen Stelle, Math.tanh. CSS leckt überall. Web Audio berührt drei Bibliotheken innerhalb eines einzigen Graphen.
WASM leckt nicht das Betriebssystem. kein transzendenter Opcode, sin stammt aus der libm, die das Modul eingebettet hat, und Arithmetik (f64.sqrt, f64.mul) basiert auf Hardware. Seine einzige Fingerprinting-Achse ist ARM vs. x86 (NaN-Kanonisierung, einige SIMD-Rundungsunterschiede).
Die vier Fallen — die eigentliche Design-Lektion, weit über dieses Thema hinaus übertragbar. 1. Nur manche Funktionen lecken. Das Fälschen der Funktionen, die nicht lecken, erzeugt eine Inkonsistenz, und „diese Asymmetrie ist selbst überprüfbar.“ → Überkorrektur ist ebenso erkennbar wie Unterkorrektur. 2. JS und CSS sind getrennte Codepfade. CSS-Trigonometriefunktionen reduzieren den Winkel in Grad und rufen dann std::sin auf den reduzierten Wert auf — ein anderes Ergebnis als ein sin() in Radiant. Das Team reproduzierte „die Gradreduktion und den Schritt von Radiant zu Grad bitgenau, nicht nur die Blattfunktion.“ 3. macOS hat zwei Mathematikbibliotheken, die sich widersprechen. Die skalare libsystem_m und Accelerates Vektorroutinen weichen je nach Funktion bei 10 bis 89 % der Eingabewerte voneinander ab. cos(0): 1.0 skalar, 0.9999999999999999 mit Accelerate. → „‚Apples Mathematik nachbilden‘ ist so lange undefiniert, bis man weiß, welche Bibliothek der Browser an welcher Stelle aufruft.“ Experimentell ermittelte Antwort: skalar für Math.tanh, CSS-Trigonometrie und die Per-Sample-Transzendenten des Kompressors; Accelerate für Web-Audio-DSP (FFT, Vektormathematik, Biquad-Filter). Die falsche Bibliothek zu wählen kostet bei den meisten Eingabewerten 1 ULP — schlimmer, als gar nichts zu tun. 4. Die Architektur leckt ebenfalls. ARM und x86 unterscheiden sich bei fused multiply-add und bei der Vorzeichenweitergabe von NaN; eine auf dem Papier korrekte Reproduktion driftet, wenn der Compiler auf der einen Seite fusioniert und auf der anderen nicht.
Warum Rauschen nicht funktioniert — ein Argument, das sich auf jede Fingerprinting-Gegenmaßnahme verallgemeinern lässt. „Die Ausgabe zu stören scheitert zweifach. Ein Referenzvergleich sieht einen Wert, der mit keinem realen Betriebssystem übereinstimmt, und die Zufälligkeit pro Aufruf bricht die Determinismus, was selbst ein Erkennungsmerkmal ist.“ → Eine Verteidigung, die einen unmöglichen Wert erzeugt, ist genauso identifizierend wie ein echter. Das Ziel ist nicht „Rauschen“, sondern der exakte Wert des behaupteten Systems.
Die gewählte Gegenmaßnahme und ihre drei Anforderungen. (1) Minimax-Koeffizienten, Exponententabellen und Reduktionskonstanten der Ziel-libm abrufen und in portablen C-Code übertragen; (2) die Bitmuster hexadezimal kopieren — „eine dezimale Transkription würde anders runden“; (3) jede Fusion als explizites fma() schreiben und mit -ffp-contract=off kompilieren, damit die fusionierten Operationen genau die sind, die Apple fusioniert, und das Ergebnis auf CPUs mit und ohne FMA identisch ist, ebenso zwischen der emulierten ARM-Maschine und der ausführenden x86-Flotte. Wenn Reproduktion den Aufwand nicht wert ist: „das Original übernehmen“ — da Windows UCRT x86-64 und positionsunabhängig ist.
Was der Artikel für browsergesteuerte Agenten impliziert. — im Text nicht ausgesprochen, aber naheliegend: Ein Agent, der einen Browser steuert, um das Web zu lesen, durchläuft genau diese Prüfungen. Harnesses, die auf den echten Browser des Nutzers eskalieren, statt einen zu imitieren (vgl. den Browser-Pfad von [[skill-gibbs-hyperresearch-2026-08-03]], der den authentifizierten echten Chrome steuert und als harte Grenze festlegt, dass „CAPTCHAs, 2FA und Logins niemals automatisch gelöst werden“), umgehen das Problem konstruktionsbedingt: Es gibt nichts zu fälschen, wenn der Browser tatsächlich das ist, was er vorgibt zu sein. Zwei entgegengesetzte Strategien vor derselben Wand.
Einordnung der Nutzung. Der Artikel dokumentiert eine Technik zur Umgehung von Erkennung, verfasst von einem Anbieter für Web-Scraping. Sie ist defensiv nutzbar (um zu verstehen, was das eigene Anti-Bot-System tatsächlich liest, und zu wissen, dass ein isoliertes Math.tanh-Signal den Browser ebenso datiert wie es das Betriebssystem identifiziert) wie auch zur Umgehung. Der Text geht nicht auf die Einwilligung der gescrapten Websites ein, ebenso wenig auf Nutzungsbedingungen — das liegt außerhalb seines erklärten Anspruchs.
KI-unterstütztes Verfassen, offengelegt. „die Beiträge hier werden mit KI verfasst … Die Mechanismen, die Zahlen und der Code stammen von uns.“ Eine ehrliche und seltene Offenlegung, erwähnenswert, wenn der Text als Primärquelle zitiert wird. Die Messungen kommen mit ihrem Protokoll (DevTools-Protokoll, drei benannte Maschinen mit ihren Versionen), was sie unabhängig überprüfbar macht, unabhängig davon, wie der Fließtext entstanden ist.
Meta / verwandt. zu browsersteuernden Agenten [[skill-gibbs-hyperresearch-2026-08-03]] (Browser-Pfad, Eskalation, CAPTCHA-Grenze); zur Angriffsfläche und Webinhalten als feindlich behandelten Daten [[valente-zalewski-beyond-zero-enterprise-security-ai-era-2026-07-20]]; zu KI-Browsern und Automatisierung [[mody-browser-company-arc-dia-ai-native-2025-11-23]], perplexity-chrome-integration-browser-ai-search-2025-10-22 und mcp-replaces-browser-logrocket-2025-09-15.
Kernzahlen
trois valeurs distinctes sur glibc, libsystem_m et UCRT pour l'entrée 0.8