Volver a la herramienta

Guía de verificación

No confíes. Comprobalo.

Cualquier sitio puede afirmar que procesa tus datos localmente. Es exactamente lo que diría también un sitio malicioso. Esta guía te enseña a comprobarlo por tu cuenta, en cuatro niveles de rigor creciente.

Antes de empezar

Usá una foto de prueba, no tu documento real. Sacale una foto a cualquier papel escrito. Se verifica primero y se usan datos reales después, nunca al revés.

Cuánto cuesta cada nivel y qué cierra Concluyente por sí solo Nivel 1. La desconexión si funciona sin conexión, no hubo transmisión 2 minutos No lo reemplazan. Cierran objeciones más específicas. Nivel 2. Mirar el tráfico descarta un envío diferido, para cuando vuelva la red 10 minutos Nivel 3. Leer el código descarta que la función de enviar exista 30 minutos Nivel 4. Capturar la red desde afuera no depende de lo que muestre el navegador una tarde
Figura 1. El primer nivel lleva dos minutos y ya es concluyente. Los siguientes no lo reemplazan: cierran objeciones cada vez más específicas. No hace falta hacerlos todos.

Nivel 01 · dos minutosLa prueba de la desconexión

Si la herramienta funciona con internet desconectado, no puede haber subido nada. No es una cuestión de confianza sino de física: no hay forma de que un archivo viaje por una conexión que no existe.

  1. Abrí el sitio y esperá a que cargue por completo.
  2. Cortá la conexión: apagá el WiFi, desenchufá el cable o activá el modo avión.
  3. Recargá la página. Debería cargar igual, porque el service worker guardó una copia en tu dispositivo.
  4. Sin conexión, hacé el recorrido entero: cargá la foto, tapá los datos y descargá el resultado.
El recorrido completo, sin conexión Tu dispositivo. Nada de esto necesita la red. Cargás la foto funciona Tapás los datos funciona Descargás el archivo funciona sin conexión Internet inalcanzable
Figura 2. Si el recorrido completo funciona con el corte puesto, el procesamiento ocurrió íntegramente en tu máquina. Es la prueba más simple y la más difícil de refutar.

Una objeción legítima

«¿Y si guarda la foto y la manda cuando vuelva la conexión?» Es un escenario razonable y esta prueba sola no lo descarta. Lo cierran el nivel 2 y la inspección del almacenamiento, ambos a continuación.

Nivel 02 · diez minutosMirar el tráfico

El navegador registra todas y cada una de las conexiones que hace una página. No se le escapa ninguna, y ese registro no lo controla el sitio.

  1. Abrí el sitio y presioná F12 o Ctrl+Shift+I para abrir las herramientas de desarrollo.
  2. Andá a la pestaña Red (Network).
  3. Tildá Conservar registro (Preserve log) y Deshabilitar caché (Disable cache).
  4. Recargá la página y hacé el recorrido completo con tu foto de prueba.

Qué buscar

Qué hacerQué deberías ver
Escribir method:POST en el filtro Nada. Subir un archivo requiere prácticamente siempre un POST.
Ordenar por la columna Tamaño Ninguna petición del orden de una foto. Una imagen pesa cientos de kilobytes o varios megabytes.
Abrir cualquier petición y mirar Payload El contenido exacto de lo que se envió, en texto.

Qué es normal encontrar: las descargas del propio sitio: el HTML, la hoja de estilos, los archivos JavaScript, el ícono y el manifest.json. Todas son descargas, es decir, el servidor te manda a vos. Ninguna es una subida.

Todas van al mismo dominio del sitio. La herramienta no carga tipografías remotas, bibliotecas externas ni herramientas de medición: la cantidad de dominios de terceros que contacta es cero.

Descartar que algo quede en cola

Para cerrar la objeción del nivel 1:

  1. Procesá una imagen con la conexión cortada.
  2. Volvé a conectar, con la pestaña de red abierta y el registro conservado.
  3. Esperá un par de minutos y navegá por el sitio.

Si no aparece ninguna subida, no había nada esperando para salir.

ComplementoQué hay guardado en tu navegador

En las herramientas de desarrollo, la pestaña Aplicación (Application) muestra todo lo que el sitio guardó en tu dispositivo. Es donde aparecería cualquier imagen almacenada. Esto es lo que vas a encontrar, y por qué:

DepósitoContenidoMotivo
Local Storage Como máximo una clave: copia-segura:theme, con el valor light o dark, es decir, claro u oscuro. La preferencia del selector de modo claro y oscuro. Si nunca lo tocaste, ni siquiera existe.
Cache Storage Los archivos de la aplicación: HTML, CSS, JavaScript y el ícono. Es lo que permite usarla sin conexión. Es código, no datos.
IndexedDB Vacío. La aplicación no lo usa.
Cookies Ninguna. No se usan cookies para nada.

Qué sería un problema

Cualquier otra cosa. En particular, una imagen guardada en cualquiera de esos depósitos contradiría lo que este proyecto afirma, y vale un reporte.

Nivel 03 · treinta minutosLeer el código

El sitio no usa empaquetadores ni minificación. Los archivos que sirve el servidor son los mismos que están publicados en el repositorio, legibles tal cual. En las herramientas de desarrollo, la pestaña Fuentes (Sources) muestra exactamente los mismos archivos que ves en GitHub.

Sacar datos de una pestaña del navegador requiere sí o sí alguna de estas primitivas de JavaScript. No existe otra forma:

grep -rnE 'fetch\(|XMLHttpRequest|sendBeacon|new WebSocket|EventSource|<form|FormData|import\(|eval\(|new Function' index.html js/ css/

Si el resultado está vacío, no hay código capaz de transmitir tu imagen. Notá que la búsqueda incluye la carpeta js/: la aplicación son varios archivos, y revisar solo el HTML dejaría afuera casi todo el código.

No te olvides del service worker

Un service worker se ejecuta aparte de la página y puede interceptar tráfico, así que hay que auditarlo por separado:

grep -inE 'fetch\(|POST|sendBeacon' sw.js

Acá sí vas a encontrar fetch(), y es correcto: un service worker de caché lo usa para traer los archivos del sitio y guardarlos. Lo que hay que revisar es que no haya ningún fetch() hacia un dominio ajeno ni ningún method: 'POST'.

La directiva que lo hace innecesario

Hay un atajo. El servidor envía una cabecera Content-Security-Policy con default-src 'self' y connect-src 'none': el navegador impide contactar cualquier dominio externo y bloquea fetch, XMLHttpRequest, sendBeacon y WebSocket, exista o no el código para intentarlo. Se comprueba en un comando:

curl -I https://copiasegura.com.ar/ | grep -i content-security-policy

Esa es la diferencia entre «no lo hace» y «no puede hacerlo».

Nivel 04 · máximo rigorCapturar la red desde afuera

Los niveles anteriores dependen de herramientas que la propia página, en teoría, podría intentar manipular. Capturar el tráfico a nivel del sistema operativo elimina esa duda: mirás los paquetes desde afuera, donde la página no tiene ninguna injerencia.

ComplementoComprobar que el sitio sirve el código publicado

Que el código del repositorio sea limpio no garantiza que el servidor esté sirviendo ese mismo código. Se comprueba comparando huellas criptográficas.

La huella SHA-256 de un archivo una barra por cifra Si el sitio sirve el código publicado sitio a5c8a20960891fee... repositorio a5c8a20960891fee... Coinciden las 64 cifras. Es el mismo archivo. Si cambió un solo carácter del archivo sitio 4536908e866042de... repositorio a5c8a20960891fee... Coinciden 6 de 64, por azar. No es el mismo archivo.
Figura 3. Un solo carácter de diferencia produce huellas completamente distintas. No hay término medio: o es el mismo archivo o no lo es. Las huellas del ejemplo son reales y se pueden reproducir: printf 'Copia Segura' | sha256sum y printf 'Copia segura' | sha256sum.
# Huella del archivo que te está sirviendo el sitio
curl -s https://copiasegura.com.ar/index.html | sha256sum

# Huella del archivo del repositorio
git clone https://github.com/fabiobritez/copiasegura
sha256sum copiasegura/index.html

Conviene repetirlo con los archivos de js/, que es donde vive la lógica que importa.

RecomendadoLa versión que no depende de ninguna promesa

Si querés sacar la confianza de la ecuación por completo, no uses el sitio hosteado:

  1. Descargá el repositorio completo desde GitHub.
  2. Desconectá internet.
  3. Abrí index.html con doble clic y usalo así.

Un archivo local que ya auditaste y que corre sin conexión no puede traicionarte. Además te blinda ante un cambio futuro: verificar hoy no dice nada sobre lo que se despliegue mañana. Para uso recurrente, es la forma recomendada.

HonestidadLos límites de esta verificación

Una guía honesta tiene que decir también lo que no cubre.

ContribuirSi encontrás algo

Si en cualquiera de estos pasos detectás una conexión que no debería existir, un dato guardado que no corresponde o una diferencia entre lo servido y lo publicado, abrí un issue en el repositorio con la captura correspondiente.

Un reporte que refute lo que afirmamos acá es la contribución más valiosa que puede recibir este proyecto, y va a ser tratado como tal.

Abrir un issue en GitHub