Una URL parece privada porque solo deberían tenerla las personas a las que se la envías. En la práctica, una URL es uno de los datos que más se registran en la web: la anotan, la copian y la reenvían sistemas que nunca te pidieron permiso y que no puedes auditar. Aquí verás exactamente dónde se filtra y cómo diseñar enlaces que aguanten esa filtración. Es también la razón por la que un generador de enlaces secretos de un solo uso guarda la clave de descifrado después del # del enlace: esa parte nunca llega al registro de un servidor.
Dónde se filtra
- Historial del navegador. Cada URL que visita el usuario se guarda en local y puede sincronizarse con otros dispositivos y con el servicio de sincronización del fabricante del navegador.
- Registros de acceso del servidor HTTP. La mayoría de los servidores registran por defecto la ruta completa de la petición y la cadena de consulta. Cualquiera con acceso a los registros tiene la URL.
- Proxies inversos y CDN. Cloudflare, Fastly, tu balanceador de carga: todos registran la URL, cada uno con su propia política de conservación.
- Canales de agregación de registros. Los registros de acceso rara vez se quedan en una sola máquina; se envían a servicios centralizados de registro y monitorización, lo que multiplica el número de sistemas que guardan la URL.
- Encabezados Referer. Cuando la página enlaza a un recurso de un
tercero, el navegador puede enviar la URL de origen en el encabezado
Referer. Los scripts de analítica, los vídeos incrustados y los píxeles publicitarios la reciben. - Extensiones del navegador. Las extensiones con permiso para «leer el historial de navegación» ven todas las URL, incluida la parte que va después del #.
- Sincronización de marcadores. Las URL guardadas como marcadores se sincronizan entre los dispositivos del usuario y con los servidores del fabricante del navegador.
- Generadores de vistas previas de URL. Slack, Teams, iMessage, LinkedIn y los clientes de correo abren las URL para mostrar vistas previas, sin avisar y en el momento en que se envía el mensaje.
- Proxies corporativos y pasarelas de correo. Muchas organizaciones inspeccionan, reescriben y registran todas las URL que cruzan su perímetro.
¿HTTPS mantiene la URL en privado?
No. HTTPS cifra la URL en tránsito y nada más; los dos extremos la siguen guardando. Merece la pena precisarlo, porque «la conexión está cifrada» se malinterpreta a menudo como «la URL es privada».
TLS cifra la ruta y la cadena de consulta en tránsito: alguien que observe la red
entre el navegador y el servidor no puede leer
/reset?token=.... Lo que TLS no oculta es el nombre del host de
destino (visible en la resolución DNS y, hoy en día, en el campo SNI de TLS en la mayoría de
las conexiones), ni nada de lo que ocurre en los extremos: el navegador
sigue guardando la URL completa en el historial y el servidor sigue escribiéndola
en su registro de acceso. El cifrado en tránsito protege el cable, no
los dos extremos, y es en los extremos donde se filtran las URL.
Un ejemplo completo: la vida de una URL
Sigamos una sola URL con datos confidenciales, por ejemplo un enlace para restablecer la contraseña,
https://example.com/reset?token=8f3a91..., desde que se envía hasta que se hace clic en ella:
- El proveedor de correo guarda el mensaje (con la URL) de forma indefinida, y su escáner de seguridad puede abrir la URL al entregarlo.
- La pasarela de correo del destinatario reescribe y registra la URL, y después la vuelve a abrir cuando se hace clic.
- El DNS resuelve
example.com: el nombre del host (no la ruta) queda ya en los registros del resolvedor. - El servidor web escribe la línea completa de la petición en su registro de acceso. Una entrada con el formato «combined» por defecto de nginx o Apache tiene este aspecto:
203.0.113.7 - - [14/Jul/2026:09:12:45 +0000]
"GET /reset?token=8f3a91... HTTP/1.1" 200 5123 "-" "Mozilla/5.0 ..."
- La CDN que tiene delante registra la misma URL con su propia política de conservación.
- El script de analítica de la página guarda la URL de la página, con la cadena de consulta incluida, en un sistema de terceros, salvo que se haya configurado de forma explícita para quitarla.
- El navegador guarda la URL en el historial y la sincroniza.
Un envío, siete copias, en manos de al menos cinco organizaciones. Nada de esto ha necesitado un atacante: es la web funcionando tal como se diseñó.
El encabezado Referer en la práctica
Si la página donde se muestra tu secreto enlaza a cualquier recurso externo (una fuente
de una CDN, un script de analítica, una imagen incrustada), el navegador puede enviar
la URL de la página en el encabezado Referer a ese origen.
Los navegadores actuales usan por defecto strict-origin-when-cross-origin
(MDN: Referrer-Policy),
que recorta el referente entre orígenes distintos y deja solo el origen
(https://example.com/ en lugar de la ruta completa). Es un avance
real, pero no algo en lo que confiar: las peticiones del mismo origen siguen
llevando la URL completa, una política definida en la página puede relajar el valor por defecto, y
los clientes antiguos y las webviews integradas no se comportan todos igual.
Dos medidas prácticas:
<!-- Strip the referer for outbound requests on the page -->
<meta name="referrer" content="no-referrer" />
Referrer-Policy: no-referrer
La versión con encabezado se aplica a todo el sitio; la metaetiqueta, a esa página concreta. Usa las dos para tener varias capas de defensa. Mejor aún: sirve las páginas con datos confidenciales sin ningún recurso de terceros, para que no haya nadie a quien enviar un referente.
¿Es más seguro poner el token en la ruta, en la cadena de consulta o después del #?
Solo la parte del enlace que va después del # queda fuera de la petición, y por eso solo esa parte queda fuera de los registros del servidor; la ruta y la cadena de consulta son equivalentes. El lugar de la URL donde pones un token cambia quién lo ve:
| Ubicación | ¿Se envía al servidor? | ¿En los registros del servidor? | ¿En el Referer? | ¿En el historial del navegador? |
|---|---|---|---|---|
Ruta (/s/abc123) | Sí | Sí | Depende de la política | Sí |
Cadena de consulta (?token=abc123) | Sí | Sí | Depende de la política | Sí |
Fragmento (#abc123) | No | No | No | Sí |
El fragmento es realmente distinto: según la RFC 3986, sección 3.5, se procesa en el cliente y nunca se incluye en la petición HTTP. Por eso los servicios para compartir texto con cifrado de extremo a extremo ponen ahí la clave de descifrado: el servidor nunca la recibe, literalmente. Aun así, no es invisible: el historial del navegador, las extensiones y cualquier JavaScript que se ejecute en la página pueden leerla. Elegir entre ruta y cadena de consulta, en cambio, no cambia nada en cuanto a privacidad: las dos acaban en los mismos registros.
El problema de los tokens para restablecer contraseñas
Los tokens confidenciales en las URL son una clase de vulnerabilidad reconocida. La CWE-598 de MITRE («Use of GET Request Method With Sensitive Query Strings») trata justo esto: los datos confidenciales de la cadena de consulta acaban en registros, historiales y referentes, aunque el transporte vaya cifrado. Por eso los procesos de restablecimiento de contraseña bien hechos nunca dependen solo de que la URL sea secreta. Hacen que el token sea de un solo uso, de corta duración y vinculado a una acción posterior (definir una nueva contraseña), de modo que un token recuperado de un registro tres semanas después no sirva para nada.
Esa es la lección general: normalmente no puedes impedir que una URL acabe en los registros, pero sí puedes hacer que la URL registrada no sirva para nada cuando alguien la lea.
Cómo diseñar URL que no importe filtrar
Da por hecho que cada URL que generes acabará apareciendo tarde o temprano donde no debería, y diséñala para que eso no importe:
- Un solo uso. Destruye el secreto después de la primera lectura correcta, para que una URL filtrada ya no funcione cuando aparezca en el historial de alguien.
- Expiración corta. Limita el tiempo durante el que la filtración importa. Una URL que funcionó durante cinco minutos vale mucho menos que una que funcionó durante una semana.
- Frase de contraseña por otro canal. Exige un secreto que nunca haya estado en la URL. Así, la URL sola (lo único que tienen los registros) no basta.
- Separa la consulta de la entrega del contenido. Devuelve los metadatos con
GETy entrega el contenido solo con unPOSTexplícito, para que los bots de vista previa y los escáneres no puedan consumir el secreto. - Ningún recurso de terceros en las páginas con datos confidenciales, además de
Referrer-Policy: no-referrery<meta name="robots" content="noindex">. - Oculta las rutas secretas en tus propios registros. En nginx, transforma la
URI de la petición antes de registrarla (consulta la referencia de
ngx_http_log_module
para
log_format):
map $request_uri $loggable_uri {
~^/s/ "/s/[redacted]";
default $request_uri;
}
log_format redacted '$remote_addr - $remote_user [$time_local] '
'"$request_method $loggable_uri" $status';
access_log /var/log/nginx/access.log redacted;
Solo controlas tus propios registros (las copias de la CDN, del proxy y del navegador siguen ahí), y precisamente por eso los tres primeros puntos de esta lista son los que más peso tienen.
Cómo influye esto en los enlaces secretos
Este modelo de amenazas explica por qué los enlaces secretos de LinkPilot funcionan como
funcionan: se parte de que la URL se acabará filtrando, así que la URL sola
nunca basta. Un GET devuelve solo metadatos; para obtener el contenido hace falta
un POST explícito para mostrarlo, que puede estar protegido por una frase de contraseña cuyo
hash SHA-256 se calcula en el cliente. Los secretos destruidos, expirados o revocados
devuelven HTTP 410 con el contenido sobrescrito de forma irreversible, las respuestas
que muestran el contenido llevan Cache-Control: no-store y los eventos de visualización registran
un hash de la IP con una sal que cambia cada día, en lugar de la dirección sin procesar.
Y un límite que reconocemos abiertamente, indicado en la página de
arquitectura de seguridad: la clave de descifrado
va en la parte del enlace que va después del #, así que hay que tratar el enlace completo como
el secreto, que es justo el riesgo del que trata este artículo. Una expiración
corta, la destrucción tras la lectura y una frase de contraseña enviada por otro canal son lo que limita
el daño cuando se filtra un enlace.
Actualización del 29 de septiembre de 2026: este párrafo decía originalmente que LinkPilot no ofrecía cifrado de extremo a extremo. Ahora cifra el texto en el navegador, archivos adjuntos incluidos.
Pruébalo gratis, sin registro
Mensaje que se autodestruye
Envía una nota que desaparece después de leerse una vez.
Límites
El diseño de las URL no lo arregla todo. No controla lo que hace el destinatario después de una lectura legítima, no puede eliminar las copias que ya tienen terceros y no salva una URL que lleva datos personales a la vista: si la dirección de correo de un usuario está en la cadena de consulta, ninguna expiración evita que quede registrada. La regla que se mantiene es esta: no pongas nunca en una URL datos que tengas que eliminar más adelante, porque eliminar una URL de todos los sitios donde se ha copiado es prácticamente imposible. Diseña, en cambio, URL que no sirvan para nada cuando se filtren.
Lecturas relacionadas
- Cómo funcionan los enlaces secretos de un solo uso
- Escáneres de enlaces y secretos de un solo uso
- Compartir contraseñas de forma segura: 5 métodos comparados
