Your Browser Does Math Differently on Every OS, and Anti-Bot Systems Read the Bits
Artículo de ingeniería publicado el 12 de julio de 2026 por Scrapfly Engineering, sobre un canal de fingerprinting de navegador poco conocido: los últimos bits de un número de coma flotante delatan el sistema operativo. El mecanismo: IEEE 754 define cómo se almacena un double, pero no exige que sin, cos, tanh o exp estén correctamente redondeados; cada sistema distribuye por tanto una libm que sacrifica una fracción de ULP a cambio de velocidad, con sus propios coeficientes minimax, tablas y constantes de reducción.
Por **Scrapfly Engineering** — équipe d'ingénierie de **Scrapfly**// Fuente scrapfly.dev ↗/Lectura 2 min/.md// Traducción verificada automáticamente
#fingerprinting#huella digital del navegador#anti-bot#detección de automatización#IEEE 754#redondeo correcto#ULP#unidad en el último lugar
Artículo de Scrapfly Engineering (12 de julio de 2026) sobre un canal de fingerprinting alojado en los últimos bits de un número.
El mecanismo. IEEE 754 define cómo se almacena un double, pero no exige el redondeo correcto de las funciones trascendentes. Como el redondeo correcto resulta costoso, cada plataforma distribuye una libm con sus propios coeficientes minimax, tablas y constantes. En consecuencia, Math.tanh(0.8) devuelve tres valores distintos según glibc, libsystem_m y UCRT. Linux y macOS divergen en aproximadamente una cuarta parte de las entradas, típicamente en 1 ULP. « Un detector no necesita matemáticas, solo una tabla. » Y la incoherencia es inmediatamente explotable: afirmar ser macOS mientras se devuelven bits de Linux contradice su propio User-Agent.
una sola llamada a tanh sobre la entrada correcta es una firma por sistema operativo. Afirma ser macOS, devuelve bits matemáticos de Linux, y te has contradicho con tu propio User-Agent.
— **Scrapfly Engineering** — équipe d'ingénierie de **Scrapfly** , scrapfly.dev
El indicio es reciente y está fechado. Hasta Chrome 147, V8 calculaba tanh con un fdlibm embebido, idéntico en todas partes. El commit c1486295ae5 lo sustituyó por std::tanh, que lee la libm del sistema anfitrión, publicado con Chrome 148.
Tres superficies tienen fuga.Math.tanh es la única función Math.* afectada — V8 embebe y enlaza estáticamente todo lo demás. Las siete funciones trigonométricas de CSS tienen fuga, con Blink llamando a la libm del sistema anfitrión tras una reducción de ángulo basada en grados que no comparte código con Math.sin. Y Web Audio toca tres bibliotecas dentro de un mismo grafo: Accelerate para las etapas de FFT y vectoriales, libsystem_m escalar para las funciones trascendentes del compresor. WASM, por su parte, no delata el sistema operativo — solo la arquitectura.
Cuatro trampas dificultan la contramedida: solo algunas funciones tienen fuga, de modo que falsificar las demás crea una asimetría detectable; JavaScript y CSS son rutas de código separadas; macOS embebe dos bibliotecas matemáticas que divergen entre sí entre un 10 y un 89% según la función, de modo que "reproducir las matemáticas de Apple" carece de sentido hasta saber cuál se llama en cada punto; y ARM y x86 difieren en la multiplicación-suma fusionada y en la propagación de NaN.
El ruido no funciona: produce un valor que no coincide con ningún sistema operativo real, y su no determinación es en sí misma una señal. El único camino es la reproducción bit a bit — coeficientes extraídos de la libm objetivo y transcritos en hexadecimal, cada fusión escrita como fma() explícito, compilada con -ffp-contract=off.
El editor declara que sus publicaciones se redactan con asistencia de IA, mientras que los mecanismos, las cifras y el código siguen siendo propios.
Puntos clave
El principio, en una línea. IEEE 754 exige el almacenamiento de un double, no el redondeo correcto de las funciones trascendentes. El redondeo correcto resulta costoso, así que cada sistema distribuye su propia libm con sus coeficientes minimax, tablas y constantes de reducción. La diferencia de redondeo es una firma.
La sonda, digna de conocerse.Math.tanh(0.8) devuelve 0.6640367702678491 en Linux (glibc), 0.664036770267849 en macOS (libsystem_m) y 0.6640367702678489 en Windows (UCRT) — los tres difieren, en 2 ULP. Linux y macOS divergen en aproximadamente una cuarta parte de todas las entradas, típicamente en 1 ULP; Windows diverge de ambos en unos pocos puntos porcentuales. → « Un detector no necesita matemáticas, solo una tabla. »
El indicio está fechado hasta el commit, y esto es lo que hace útil el artículo. hasta Chrome 147, V8 calculaba tanh con un port de fdlibm embebido — mismos bits en todas partes, sin fuga. El commit de V8 c1486295ae5 lo sustituyó por std::tanh, que lee la libm del sistema anfitrión; publicado en V8 14.8.57 = Chrome 148. 148, 149, 150 tienen fuga. 147 y anteriores no. → Una regresión de privacidad introducida por una elección de implementación mundana, y una ventana de versión precisa para fechar una huella.
El mapa de fugas — la parte más reutilizable. | Operación | Math. (JS) | CSS calc() | Web Audio | |---|---|---|---| | sin cos tan | embebido en V8 | libm del sistema anfitrión | Accelerate (FFT), escalar en el compresor | | asin acos atan atan2 | embebido en V8 | libm del sistema anfitrión | no se usa | | tanh | libm del sistema anfitrión | — | no se usa | | exp, log, pow | embebido en V8 | libm del sistema anfitrión | escalar en el compresor | | vectorial, FFT | — | — | Accelerate (vDSP) en Mac | | sqrt, aritmética | hardware | hardware | hardware | → V8 enruta casi todo a través de sus propias matemáticas embebidas: JavaScript solo tiene fuga en un punto, Math.tanh. CSS tiene fuga en todas partes. Web Audio toca tres bibliotecas dentro de un mismo grafo.
WASM no delata el sistema operativo. no hay opcode trascendente, sin proviene de la libm que el módulo haya embebido, y la aritmética (f64.sqrt, f64.mul) es de hardware. Su único eje de fingerprinting es ARM frente a x86 (canonicalización de NaN, algunas diferencias de redondeo SIMD).
Las cuatro trampas — la verdadera lección de diseño, transponible mucho más allá de este tema. 1. Solo algunas funciones tienen fuga. Falsificar las funciones que no tienen fuga crea una incoherencia, y « esa asimetría es en sí misma comprobable. » → Sobrecorregir es tan detectable como subcorregir. 2. JS y CSS son rutas de código distintas. Las funciones trigonométricas de CSS reducen el ángulo en grados y luego llaman a std::sin sobre el valor reducido — un resultado distinto al de un sin() en radianes. El equipo reprodujo « la reducción en grados y el paso de radianes a grados bit a bit, no solo la función final. » 3. macOS tiene dos bibliotecas matemáticas que se contradicen entre sí. El libsystem_m escalar y las rutinas vectoriales de Accelerate divergen en un 10 a 89% de las entradas según la función. cos(0): 1.0 en escalar, 0.9999999999999999 en Accelerate. → « "Reproducir las matemáticas de Apple" carece de definición hasta saber qué biblioteca llama el navegador, y en qué punto. » Respuesta establecida experimentalmente: escalar para Math.tanh, la trigonometría de CSS y las funciones trascendentes por muestra del compresor; Accelerate para el DSP de Web Audio (FFT, matemáticas vectoriales, filtros biquad). Elegir la biblioteca equivocada cuesta 1 ULP en la mayoría de las entradas — peor que no hacer nada. 4. La arquitectura también tiene fuga. ARM y x86 difieren en la multiplicación-suma fusionada y en la propagación del signo de NaN; una reproducción correcta sobre el papel se desvía si el compilador fusiona en un lado y no en el otro.
Por qué el ruido no funciona — un argumento generalizable a cualquier contramedida de fingerprinting.« Perturbar la salida falla dos veces. Una comparación de referencia ve un valor que no coincide con ningún sistema operativo real, y la aleatoriedad entre llamadas rompe la determinación, lo cual es en sí mismo un indicio. » → Una defensa que produce un valor imposible resulta tan identificable como un valor verdadero. El objetivo no es "ruido", es el valor exacto del sistema reclamado.
La contramedida elegida, y sus tres requisitos. (1) recuperar los coeficientes minimax, las tablas de exponentes y las constantes de reducción de la libm objetivo y transcribirlas en C portable; (2) copiar los patrones de bits en hexadecimal — « una transcripción decimal redondearía de forma distinta »; (3) escribir cada fusión como fma() explícito y compilar con -ffp-contract=off, de modo que las operaciones fusionadas sean exactamente las que fusiona Apple y el resultado sea idéntico en CPU con y sin FMA, y entre la máquina ARM emulada y la flota x86 que ejecuta. Cuando la reproducción no vale el esfuerzo: « tomar el original » — puesto que Windows UCRT es x86-64 y código independiente de la posición.
Lo que el artículo implica para los agentes de navegación. — no se afirma en el texto, pero es directo: un agente que dirige un navegador para leer la web se enfrenta exactamente a estas comprobaciones. Los harnesses que escalan al navegador real del usuario en lugar de imitar uno (cf. la ruta de navegador de [[skill-gibbs-hyperresearch-2026-08-03]], que dirige el Chrome real autenticado y establece como límite absoluto que « los CAPTCHA, el 2FA y los inicios de sesión nunca se resuelven automáticamente ») esquivan el problema por construcción: no hay nada que falsificar cuando el navegador realmente es lo que afirma ser. Dos estrategias opuestas frente al mismo muro.
Encuadre de uso. el artículo documenta una técnica de evasión de detección, escrita por un proveedor de web scraping. Es utilizable de forma defensiva (comprender qué lee realmente el propio sistema antibot, y saber que una señal aislada de Math.tanh fecha el navegador tanto como identifica el sistema operativo) y también para la evasión. El texto no aborda el consentimiento de los sitios raspados, ni las condiciones de servicio — eso queda fuera de su alcance declarado.
Redacción asistida por IA, divulgada.« las publicaciones aquí se redactan con IA… Los mecanismos, las cifras y el código son nuestros. » Una divulgación honesta y poco frecuente, digna de mención al citar el texto como fuente primaria. Las mediciones vienen acompañadas de su protocolo (protocolo DevTools, tres máquinas nombradas con sus versiones), lo que las hace verificables de forma independiente sin importar cómo se haya producido la prosa.
Meta / relacionados. sobre agentes que dirigen navegadores, [[skill-gibbs-hyperresearch-2026-08-03]] (ruta de navegador, escalado, límite de CAPTCHA); sobre superficie de ataque y contenido web tratado como dato hostil, [[valente-zalewski-beyond-zero-enterprise-security-ai-era-2026-07-20]]; sobre navegadores de IA y automatización, [[mody-browser-company-arc-dia-ai-native-2025-11-23]], perplexity-chrome-integration-browser-ai-search-2025-10-22, y mcp-replaces-browser-logrocket-2025-09-15.
Cifras clave
trois valeurs distinctes sur glibc, libsystem_m et UCRT pour l'entrée 0.8