Huella digital

Fingerprinting de cuota: el disco como identidad

Cómo StorageManager.estimate() expone el tamaño del disco como señal de rastreo, y cómo controlar las respuestas de cuota de almacenamiento a nivel del motor del navegador.

Documentación

Prefieres la documentación del producto mantenida?

Este artículo tiene una página equivalente en el centro de documentación. Usa los docs para el flujo canónico, las flags actuales y la referencia duradera.

Introducción

La API Storage Manager fue introducida para ayudar a las aplicaciones web a entender cuánto espacio de almacenamiento está disponible para sus datos. A través de navigator.storage.estimate(), un sitio web puede consultar la cuota de almacenamiento aproximada (espacio máximo disponible) y el uso actual (cuánto se ha consumido). Esta información ayuda a las aplicaciones a tomar decisiones sobre estrategias de caché, almacenamiento de datos sin conexión y si solicitar al usuario que libere espacio.

La API fue diseñada con buenas intenciones. Las aplicaciones web progresivas, las aplicaciones offline-first y los sitios con contenido multimedia pesado se benefician de conocer su presupuesto de almacenamiento. Sin embargo, el valor de cuota devuelto por navigator.storage.estimate() se deriva de las características reales del disco del dispositivo. Chrome, por ejemplo, típicamente asigna una cuota basada en un porcentaje del espacio total disponible en disco. Esto significa que el valor devuelto revela indirectamente información sobre el hardware de almacenamiento físico del usuario, creando una señal de huella digital que persiste entre sesiones y sobrevive a las medidas de privacidad comunes.

Impacto en la privacidad

La huella digital por cuota de almacenamiento es preocupante porque la configuración del disco es una característica estable y específica del hardware. A diferencia de las cookies o los datos de sesión, el espacio disponible en disco de un dispositivo cambia lentamente (solo cuando se añaden, eliminan archivos o se reemplaza una unidad). Esto significa que el valor de la cuota de almacenamiento es un identificador persistente.

Las implicaciones de privacidad son significativas:

  • Identificación del tamaño del disco: Un dispositivo con un SSD de 256 GB produce un valor de cuota diferente al de uno con 512 GB o 1 TB. Dado que los tamaños de disco siguen niveles de fabricación estándar (128, 256, 512, 1024 GB), el valor de cuota efectivamente revela el nivel de almacenamiento.
  • Inferencia de patrones de uso: La proporción entre cuota y uso revela qué tan lleno está el disco. Un disco casi lleno (alto uso relativo a la cuota) se comporta diferentemente de un sistema recién instalado. Con el tiempo, los cambios en esta proporción pueden revelar patrones de actividad del usuario.
  • Identificación del sistema operativo: Diferentes sistemas operativos calculan las cuotas de almacenamiento de manera diferente. Chrome en Windows, macOS y Linux aplica fórmulas y límites diferentes, lo que significa que el mismo disco físico produce diferentes valores de cuota dependiendo del SO.
  • Identificación de clase de dispositivo: Un dispositivo con una unidad de 2 TB probablemente es un escritorio o portátil de gama alta, mientras que 64 GB sugiere un portátil económico o Chromebook. Esta información de clase de dispositivo complementa otras señales de hardware.

Una investigación de la Universidad de Adelaide demostró que los valores de cuota de almacenamiento, combinados con otras señales relacionadas con el almacenamiento (disponibilidad de IndexedDB, comportamiento de la API Cache, estado de permiso de almacenamiento persistente), podían aumentar la unicidad de la huella digital entre un 5-10%. La API no requiere permisos y no produce notificaciones.

El problema se agrava por el hecho de que el valor de cuota no es estático por dispositivo. Cambia a medida que se usa y se libera espacio en disco, creando un identificador que evoluciona lentamente y puede ser rastreado a lo largo del tiempo. Un usuario cuya cuota disminuye 20 GB durante un mes está dejando un rastro de estado de almacenamiento que puede correlacionarse con otras señales.

Contexto técnico

Cómo funciona navigator.storage.estimate()

El método navigator.storage.estimate() devuelve una promesa que se resuelve con un objeto con dos propiedades:

  • quota: El espacio total de almacenamiento disponible para el origen, en bytes. Típicamente es un porcentaje del espacio total en disco, sujeto a límites y políticas específicas del navegador.
  • usage: La cantidad de espacio de almacenamiento consumido actualmente por el origen, en bytes. Incluye datos en IndexedDB, API Cache, registros de service workers y otros mecanismos de almacenamiento.

Chrome calcula la cuota como aproximadamente el 60% del espacio total disponible en disco, con límites adicionales por origen. Firefox usa una fórmula diferente basada en el espacio libre disponible. Safari impone límites más estrictos por origen con un mecanismo de aumento basado en solicitudes.

Detalles del cálculo de cuota

En Chrome (y navegadores basados en Chromium), el cálculo de la cuota de almacenamiento sigue esta lógica aproximada:

  1. Determinar el tamaño total del volumen de la partición del disco que contiene el directorio del perfil
  2. Calcular el espacio libre disponible en esa partición
  3. Aplicar una fórmula basada en porcentaje (aproximadamente 60% del total para almacenamiento temporal, con un pool compartido entre orígenes)
  4. Aplicar límites por origen para evitar que cualquier origen consuma toda la cuota

El resultado es que dos máquinas con diferentes tamaños de disco producen valores de cuota mediblemente diferentes, incluso cuando ambas ejecutan la misma versión del navegador en el mismo sistema operativo.

Señales de IndexedDB y API Cache

Más allá de navigator.storage.estimate(), otras APIs de almacenamiento pueden filtrar información del disco:

  • IndexedDB: El tamaño máximo de la base de datos está influenciado por la cuota de almacenamiento. Intentar almacenar blobs cada vez más grandes puede revelar la cuota aproximada a través de los límites de éxito/fallo.
  • API Cache: Similar a IndexedDB, la API Cache comparte la misma cuota de almacenamiento, e intentar almacenar respuestas grandes revela los límites de cuota.
  • Almacenamiento persistente: El método navigator.storage.persist() solicita almacenamiento persistente (no sujeto a desalojo). Si esto tiene éxito y cómo afecta la cuota depende de la plataforma.

Precisión del valor

El valor de quota se devuelve en bytes, proporcionando una precisión muy alta. Una unidad de 512 GB podría producir una cuota de 307,200,000,000 bytes (aproximadamente 60% de 512 GB), mientras que una unidad de 256 GB produce aproximadamente 153,600,000,000. El valor exacto depende del espacio libre real, otros perfiles y la sobrecarga del SO, pero el orden de magnitud distingue de manera confiable los tamaños de disco.

Esta precisión significa que incluso pequeñas diferencias en la configuración del disco, como diferentes diseños de particiones o diferentes cantidades de espacio usado, producen valores de cuota distinguibles.

Diferencias entre navegadores

Diferentes navegadores calculan las cuotas de manera diferente:

  • Chrome: Porcentaje del espacio total en disco con límites por origen
  • Firefox: Basado en espacio libre disponible, con diferentes cálculos por niveles
  • Safari: Límites fijos por origen (típicamente 1 GB inicialmente, ampliable con permiso del usuario)
  • Edge: Igual que Chrome (basado en Chromium)

Estas diferencias significan que el mismo dispositivo físico produce diferentes valores de cuota en diferentes navegadores, añadiendo otra dimensión a la huella digital.

Enfoques comunes de protección y sus limitaciones

VPNs y servidores proxy

Las VPNs no tienen efecto en los valores de cuota de almacenamiento. La cuota está determinada completamente por la configuración del disco local y el cálculo del navegador. Las herramientas de privacidad a nivel de red no pueden modificar las características de almacenamiento local.

Modo incógnito y navegación privada

Los modos de navegación privada cambian el comportamiento de la cuota de almacenamiento, pero no de una manera que ayude a la privacidad. En modo incógnito, algunos navegadores reportan una cuota significativamente reducida (ya que los datos se almacenan en un sistema de archivos temporal), y la cuota puede diferir del modo normal. Esta diferencia se convierte en sí misma en una señal para detectar el modo incógnito, en lugar de mejorar la privacidad.

Extensiones de navegador

Las extensiones pueden interceptar la promesa de navigator.storage.estimate() y devolver valores modificados:

  • Valores fijos: Devolver una cuota codificada (p.ej., siempre 100 GB) es detectable si el valor no cambia entre sesiones o no se correlaciona con otras señales relacionadas con el disco.
  • Redondeo: Redondear la cuota a un valor común reduce la precisión pero puede no coincidir con el valor esperado para la combinación de navegador y SO que se está emulando.
  • Intercepción de promesas: Anular navigator.storage.estimate o su prototipo es detectable a través de verificaciones de descriptores de propiedades e inspección de la cadena de prototipos.

Reducir el uso de disco

Usar una partición o disco más pequeño sí cambia la cuota, pero los usuarios no pueden controlar fácilmente su tamaño de disco con fines de privacidad. Esta es una característica a nivel de hardware que es fundamentalmente difícil de modificar.

El enfoque a nivel de motor de BotBrowser

BotBrowser controla las respuestas de cuota de almacenamiento a nivel del motor del navegador. Cuando se carga un perfil de huella digital, todas las consultas relacionadas con el almacenamiento devuelven valores definidos por el perfil en lugar de calculados a partir del disco real de la máquina host.

Valores de cuota basados en perfil

chrome --bot-profile="/path/to/profile.enc" \
       --user-data-dir="$(mktemp -d)"

El perfil incluye valores de cuota de almacenamiento capturados de dispositivos reales. Estos valores son realistas para la clase de dispositivo objetivo del perfil: un perfil que representa un portátil con un SSD de 512 GB reporta valores de cuota consistentes con esa configuración, independientemente del tamaño de disco real de la máquina host.

Señales de almacenamiento internamente consistentes

BotBrowser asegura que todas las APIs relacionadas con el almacenamiento produzcan resultados consistentes:

  • navigator.storage.estimate() devuelve valores de cuota y uso definidos por el perfil
  • El comportamiento de almacenamiento de IndexedDB se alinea con la cuota reportada
  • El comportamiento de la API Cache es consistente con el presupuesto de almacenamiento
  • La proporción cuota/uso es realista para la clase de dispositivo objetivo
  • Los valores permanecen estables durante toda la sesión

Precisión multiplataforma

Debido a que diferentes navegadores calculan las cuotas de manera diferente, los perfiles de BotBrowser incluyen valores de cuota específicos del navegador. Un perfil de Chrome devuelve cálculos de cuota apropiados para Chrome, mientras que las diferencias de fórmula subyacentes entre navegadores se tienen en cuenta en los datos del perfil.

Prevenir filtraciones del disco host

El objetivo principal es evitar que la configuración de disco de la máquina host se filtre a través de las APIs de almacenamiento. Ya sea que BotBrowser se ejecute en un servidor de 128 GB o una estación de trabajo de 4 TB, los valores de cuota de almacenamiento reportados a las páginas web reflejan el dispositivo objetivo del perfil, no el hardware host real.

Control del valor de uso

El valor de usage (almacenamiento consumido actualmente) también está controlado. Un perfil recién cargado reporta un uso mínimo, y el valor evoluciona naturalmente a medida que el origen almacena datos durante la sesión, pero siempre dentro del contexto del marco de cuota del perfil.

Configuración y uso

Uso básico por CLI

La protección de cuota de almacenamiento es automática al cargar un perfil:

chrome --bot-profile="/path/to/profile.enc" \
       --user-data-dir="$(mktemp -d)"

No se necesitan flags adicionales.

Integración con Playwright

const { chromium } = require('playwright-core');

(async () => {
  const browser = await chromium.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      '--bot-profile=/path/to/profile.enc',
    ],
    headless: true,
  });

  const context = await browser.newContext({ viewport: null });
  const page = await context.newPage();

  const storageInfo = await page.evaluate(async () => {
    const estimate = await navigator.storage.estimate();
    return {
      quota: estimate.quota,
      usage: estimate.usage,
      quotaGB: (estimate.quota / (1024 ** 3)).toFixed(2),
      usageMB: (estimate.usage / (1024 ** 2)).toFixed(2),
    };
  });

  console.log('Storage info:', storageInfo);
  await browser.close();
})();

Integración con Puppeteer

const puppeteer = require('puppeteer-core');

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      '--bot-profile=/path/to/profile.enc',
    ],
    headless: true,
    defaultViewport: null,
  });

  const page = await browser.newPage();
  await page.goto('about:blank');

  const quota = await page.evaluate(async () => {
    const est = await navigator.storage.estimate();
    return { quota: est.quota, usage: est.usage };
  });

  console.log('Quota:', quota.quota, 'bytes');
  console.log('Usage:', quota.usage, 'bytes');
  await browser.close();
})();

Combinado con otras protecciones

Para un control completo de la identidad del dispositivo:

chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=42 \
       --proxy-server="socks5://user:pass@proxy:1080" \
       --bot-config-timezone="America/Chicago" \
       --user-data-dir="$(mktemp -d)"

Verificación

Después de lanzar BotBrowser con un perfil, verifica los valores de cuota de almacenamiento:

const estimate = await navigator.storage.estimate();
const quotaGB = (estimate.quota / (1024 ** 3)).toFixed(2);
const usageMB = (estimate.usage / (1024 ** 2)).toFixed(2);

console.log(`Quota: ${quotaGB} GB (${estimate.quota} bytes)`);
console.log(`Usage: ${usageMB} MB (${estimate.usage} bytes)`);

// Verifica que la cuota refleje el perfil, no el host
// Un perfil para un dispositivo de 256 GB debería mostrar aproximadamente el 60% de 256 GB
// Un perfil para un dispositivo de 1 TB debería mostrar un valor proporcionalmente mayor

Qué verificar:

  1. El valor de cuota es realista para la clase de dispositivo objetivo del perfil (no para la máquina host)
  2. La cuota no coincide con el tamaño real del disco de tu host
  3. El valor de uso es razonable (bajo para una sesión nueva, aumentando a medida que se almacenan datos)
  4. Los valores permanecen estables entre recargas de página dentro de la misma sesión
  5. Diferentes perfiles producen diferentes valores de cuota
  6. Las herramientas de prueba de huella digital no muestran anomalías relacionadas con el almacenamiento

Mejores prácticas

  1. Usa perfiles completos. Los valores de cuota de almacenamiento deben ser consistentes con el resto de la identidad del dispositivo. Un perfil que afirma ser un dispositivo móvil no debería reportar una cuota de 2 TB.

  2. Adapta user-data-dir al caso de uso. Un user-data-dir nuevo (usando mktemp -d) comienza con un uso mínimo. Para sesiones persistentes, reutiliza el mismo directorio de datos para que los valores de uso evolucionen naturalmente.

  3. Considera la detección de modo incógnito. Si tu flujo de trabajo requiere evitar la detección de modo incógnito, ten en cuenta que el comportamiento de la cuota de almacenamiento difiere entre el modo normal y el incógnito. Los perfiles de BotBrowser en modo normal reportan valores de cuota estándar.

  4. Verifica contra tu host real. Ejecuta navigator.storage.estimate() en tu máquina host fuera de BotBrowser para conocer tu valor de cuota real, luego confirma que el perfil de BotBrowser reporta un valor diferente.

Preguntas frecuentes

¿La cuota de almacenamiento revela el tamaño exacto del disco?

No exactamente. La cuota es un porcentaje del espacio disponible en disco (aproximadamente 60% en Chrome), y cambia a medida que se usa el espacio en disco. Sin embargo, el valor de cuota distingue de forma confiable entre niveles de tamaño de disco (128 GB vs. 256 GB vs. 512 GB vs. 1 TB), haciéndolo una señal de huella digital útil.

¿Pueden los sitios web sondear los límites de almacenamiento sin navigator.storage.estimate()?

Sí. Intentando escribir blobs cada vez más grandes en IndexedDB o la API Cache, un sitio web puede descubrir el límite de almacenamiento por prueba y error. BotBrowser controla el sistema de cuota subyacente, por lo que tanto la API de estimación como el comportamiento real de almacenamiento reflejan la configuración del perfil.

¿La cuota de almacenamiento cambia en modo incógnito?

Sí. El modo incógnito típicamente usa un sistema de archivos temporal con una cuota diferente. El valor de cuota en modo incógnito es a menudo significativamente menor que en modo normal, lo cual puede usarse para detectar la navegación en modo incógnito. Los perfiles de BotBrowser en modo normal reportan valores de cuota estándar.

¿Qué tan precisa es la cuota como huella digital?

El valor de quota se devuelve en bytes, proporcionando una precisión muy alta. Sin embargo, debido a que el valor fluctúa a medida que cambia el espacio en disco, es más útil como identificador grueso (nivel de tamaño de disco) que como uno preciso. Cuando se combina con otras señales, contribuye significativamente a la huella digital general.

¿BotBrowser controla la API de almacenamiento persistente?

El método navigator.storage.persist() y su comportamiento asociado están controlados por el perfil. El perfil determina si el almacenamiento persistente está disponible y cómo los cálculos de cuota se ven afectados por el estado de persistencia.

¿Qué hay de la API obsoleta webkitStorageInfo?

Las versiones anteriores de Chromium exponían la cuota de almacenamiento a través de webkitStorageInfo y navigator.webkitTemporaryStorage. Los perfiles de BotBrowser controlan estas APIs heredadas también, asegurando que los scripts de huella digital más antiguos reciban valores consistentes.

¿Puede la cuota de almacenamiento revelar si se ejecuta en un contenedor?

Los contenedores y máquinas virtuales a menudo tienen asignaciones de disco más pequeñas que las máquinas físicas. Un contenedor Docker con un volumen de 20 GB produce una cuota muy diferente a una máquina física con un SSD de 1 TB. El enfoque basado en perfiles de BotBrowser asegura que la cuota reportada coincida con el dispositivo objetivo, no con el almacenamiento real del contenedor.

Resumen

La API navigator.storage.estimate() del Storage Manager expone características del disco que sirven como señal de huella digital persistente. El valor de cuota revela indirectamente el tamaño del disco, la clase de dispositivo y el sistema operativo a través de fórmulas de cálculo específicas del navegador. BotBrowser controla todas las respuestas de cuota de almacenamiento a nivel del motor a través de su sistema de perfiles, asegurando que los valores reportados coincidan con el dispositivo objetivo y no filtren información sobre la configuración real del disco de la máquina host. Para protección relacionada, consulta protección de propiedades del navegador, control de temporización de rendimiento y gestión integral de perfiles.

#Storage#Quota#fingerprinting#Privacy#Indexeddb#Disk

Lleva BotBrowser de la investigación a producción

Usa estas guías para entender el modelo y después avanzar hacia validación multiplataforma, contextos aislados y despliegue de navegador preparado para escalar.