|

5 errores de HSTS que te rompen el sitio en producción

En pocas palabras: Los 5 errores de HSTS que rompen producción comparten un patrón: se cometen en tráfico real, con políticas agresivas que el navegador cachea durante semanas. Según el análisis de Rasika Dangamuwa (dev.to, agosto 2026), el tiempo de recuperación se mide en semanas. Deja tu sitio offline.

Si configuraste HSTS alguna vez, sabés que el header parece una pavada: una línea en el server y listo. Pero cuando algo sale mal con el Strict-Transport-Security, no es un error que se arregla con un deploy rápido. El navegador cachea la política y tu sitio queda offline para todos los que lo visitaron, a veces durante meses. Según un análisis reciente de Rasika Dangamuwa en dev.to (agosto 2026), los errores configuración HSTS más graves comparten un patrón: se cometen en producción, con tráfico real, y el tiempo de recuperación se mide en semanas.

HSTS (HTTP Strict Transport Security) es un mecanismo de seguridad web que obliga al navegador a conectarse exclusivamente por HTTPS a un dominio, incluso si el usuario escribe “http://” en la barra de direcciones. Lo define la RFC 6797 y funciona mediante un header que el servidor envía en la respuesta HTTPS: el navegador lo cachea y, a partir de ese momento, rechaza cualquier conexión sin cifrar hacia ese dominio y —si usaste includeSubDomains— hacia todos sus subdominios.

En 30 segundos

  • El header HSTS solo funciona si se envía por HTTPS (puerto 443); mandarlo por HTTP (puerto 80) es ignorado por el navegador según la RFC 6797.
  • Activar preload sin auditar todos los subdominios rompe dashboards internos, VPNs y servicios que no tengan certificado TLS.
  • Los headers duplicados entre el proxy inverso y el backend generan comportamiento impredecible en distintos navegadores.
  • El max-age de HSTS es un TTL deslizante: se renueva en cada visita y solo se borra sirviendo max-age=0 por HTTPS.

Cloudflare es una red de entrega de contenido (CDN) y de seguridad web desarrollada por Cloudflare Inc., diseñada para acelerar y proteger sitios web mediante un proxy inverso y mitigación de ataques DDoS.

¿Qué es HSTS y por qué un simple header puede dejarte el sitio offline?

HSTS es una política de seguridad que se transmite con este header:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Ese número (63072000) equivale a dos años en segundos. Durante ese tiempo, el navegador no intenta conectarse por HTTP ni acepta certificados inválidos. Si configurás mal el header y tu sitio deja de responder por HTTPS, los usuarios que ya lo visitaron no pueden volver a entrar. No hay un botón de “deshacer” en el lado del cliente que funcione sin acceso al servidor.

El problema de fondo es que HSTS se diseñó para proteger contra ataques de stripping SSL, y esa protección es agresiva por definición. Si el navegador pudiera desactivarla fácilmente, el atacante también podría. Por eso las consecuencias de una mala configuración son tan dolorosas.

Error 1: Mandar el header HSTS por HTTP (y por qué el navegador lo ignora)

Este es el error más común y el más fácil de cometer cuando armás la configuración de Nginx o Apache a las apuradas. Ponés el header en el bloque del puerto 80 junto con el redirect, y te quedás tranquilo. Pero la RFC 6797 es clara: los user agents solo registran la política HSTS si la reciben por una conexión TLS verificada. Si el header viaja por HTTP, el navegador lo descarta sin avisar.

¿Por qué? Porque el tráfico HTTP se puede interceptar y modificar. Un atacante podría inyectar un header HSTS falso con un max-age descomunal y bloquear el acceso legítimo. La solución es simple pero requiere mover el header al lugar correcto: Esto se conecta con lo que analizamos en gestionar variables y secretos en Cloudflare.

Configuración incorrecta en Nginx (NO hagas esto):

server {
  listen 80;
  server_name example.com;
  return 301 https://$host$request_uri;
  add_header Strict-Transport-Security "max-age=63072000" always;
}

Configuración correcta (solo en el bloque TLS):

server {
  listen 443 ssl;
  server_name example.com;
  ssl_certificate /etc/ssl/certs/example.crt;
  ssl_certificate_key /etc/ssl/private/example.key;
  add_header Strict-Transport-Security "max-age=63072000" always;
}

Ojo con esto: no es que el header “no funcione del todo” si lo mandás por HTTP. Directamente no se registra. El navegador hace de cuenta que no lo vio. Y vos podés pasar meses pensando que tenés HSTS activado cuando en realidad estás expuesto a ataques de stripping.

Error 2: Activar preload sin hacer inventario de subdominios

El mecanismo de preload de HSTS es un arma de doble filo. Cuando sometés tu dominio a hstspreload.org, los navegadores (Chrome, Firefox, Safari, Edge) incluyen tu dominio en una lista hardcodeada dentro del binario. ¿El resultado? Incluso en la primera visita, antes de que el usuario reciba el header del servidor, el navegador ya sabe que solo debe conectarse por HTTPS.

Suena bárbaro. El problema: el preload aplica a todos los subdominios sin excepción. Si tenés un panel interno tipo vpn.interno.example.com o un dashboard viejo sin certificado TLS, esa URL se vuelve inaccesible en el acto. Y sacar un dominio de la lista de preload tarda entre 6 y 12 semanas porque depende de los ciclos de release de cada navegador.

El schedule seguro para evitar desastres es:

SemanaHeaderQué validar
Semana 1max-age=2592000 (30 días)Certificados, redirects, endpoints internos
Semana 2max-age=2592000; includeSubDomainsTodos los subdominios responden por HTTPS
Mes 1max-age=63072000; includeSubDomainsMonitoreo de errores en staging
Mes 2+max-age=63072000; includeSubDomains; preloadSolo si todo el inventario de subdominios está cubierto
errores configuración HSTS diagrama explicativo

Si tu dominio es nuevo o heredaste infraestructura que no conocés del todo, mantenete en los primeros niveles durante meses. No hay apuro que justifique dejar tirados a los usuarios de un subdominio olvidado. Lo explicamos a fondo en evitar caídas con DNS autoritativos.

Error 3: Headers HSTS duplicados cuando usás proxy inverso o CDN

Terminás TLS en Cloudflare, en un ALB de AWS o en Traefik, pero tu backend en Express, Go o Django también agrega el header HSTS —porque alguien configuró Helmet con sus defaults y nadie se acordó de desactivarlo en producción. El navegador recibe dos headers distintos y, según el caso, puede ignorar ambos o aplicar uno solo de forma impredecible.

La regla es simple: solo la capa que termina TLS debe agregar HSTS. Si tu proxy ya lo hace, desactivá el header en el backend. Para verificar qué está llegando realmente al cliente, usá curl:

curl -sI https://example.com | grep -i "^strict-transport-security"

Si ves dos líneas con políticas distintas, tenés un problema. Y si los max-age difieren, el comportamiento en Chrome puede ser distinto al de Firefox, porque cada navegador resuelve el conflicto a su manera (spoiler: ninguno documenta bien qué hace en este caso).

Error 4: Usar subdominios de producción para desarrollo local

Ponele que tu equipo usa local.example.com para desarrollo. Un día entrás a producción, el navegador cachea la política HSTS con includeSubDomains, y cuando volvés a tu entorno local… ERR_SSL_PROTOCOL_ERROR. El navegador está forzando HTTPS en un subdominio que solo existe en localhost y no tiene certificado.

Esto es particularmente molesto porque no es un error de configuración del servidor: es un problema del navegador que se niega a conectarse, y no hay forma de saltarlo con un simple “Avanzado > Continuar”. Para más detalles técnicos, mirá comparativa de arranque en frío entre Cloudflare y AWS.

La solución es usar dominios reservados para desarrollo local como .localhost, .test o .example (que están definidos en la RFC 6761 y los navegadores no les aplican HSTS). Si necesitás sí o sí usar un subdominio real, generá certificados locales con mkcert y confiá en ellos.

Para limpiar manualmente la caché HSTS en Chrome, entrá a chrome://net-internals/#hsts, buscá el dominio y borralo. Pero esto solo arregla tu máquina —si tenés 20 developers con el mismo problema, preparate para una tarde de screen sharing.

Error 5: El max-age no es fijo, se renueva en cada visita

Este es el detalle que muchos pasan por alto: el max-age de HSTS no es una fecha de vencimiento fija, es un TTL deslizante. Cada vez que el navegador recibe una respuesta HTTPS válida con el header, el contador vuelve a cero. Si un usuario visitó tu sitio el día 364 de una política de 365 días, el temporizador se resetea a 365 días completos.

¿Qué implica esto? Que si decidís desactivar HSTS en un dominio, no alcanza con borrar el header de la configuración. Los usuarios que ya visitaron el sitio van a seguir forzando HTTPS hasta que expire el TTL de su última visita, que puede ser dentro de un año. Para desactivarlo explícitamente, tenés que servir:

Strict-Transport-Security: max-age=0; includeSubDomains

Y sí, esto solo funciona si lo servís por HTTPS. Si ya perdiste el certificado y no podés levantar TLS, estás en un problema serio: el navegador no acepta la directiva max-age=0 por HTTP, y sin HTTPS no podés comunicarle nada. Es un círculo vicioso del que solo se sale regenerando el certificado o esperando a que el TTL expire en cada cliente.

Tabla comparativa: los 5 errores de configuración HSTS

ErrorCausaConsecuenciaPrevención
Header por HTTPHSTS en bloque puerto 80Política ignorada, sitio expuestoMover header al bloque TLS (443)
Preload sin inventarioSubdominios sin certificado TLSDashboards y VPNs inaccesiblesAuditar subdominios antes de preload
Headers duplicadosProxy y backend agregan HSTSComportamiento impredecibleHSTS solo en capa de terminación TLS
Subdominios en dev localincludeSubDomains + localhostERR_SSL_PROTOCOL_ERRORUsar .localhost, .test o mkcert
TTL deslizantemax-age se renueva en cada visitaImposible desactivar sin HTTPSServir max-age=0 por HTTPS

Cómo probar tu configuración HSTS sin romper nada

Antes de mandar un cambio a producción, hay varias formas de validar que el header se está sirviendo correctamente y que no hay conflictos. La más directa es usar curl -sI https://tudominio.com y revisar la salida. También podés usar herramientas como el Nutilz HSTS Generator para verificar la sintaxis y compatibilidad de tus directivas antes de deployar.

Si estás en Cloudflare, el panel tiene una sección específica para HSTS dentro de SSL/TLS > Edge Certificates. Ahí podés activarlo con un toggle, configurar el max-age y decidir si aplicás includeSubDomains y preload. La ventaja de usar Cloudflare para esto es que el header se agrega en el edge y no dependés de la configuración de tu servidor de origen, reduciendo el riesgo de headers duplicados. En alternativas de almacenamiento sin costo de egreso profundizamos sobre esto.

Para entornos con múltiples ambientes (staging, QA, producción), conviene usar dominios separados en lugar de subdominios. Así evitás que el includeSubDomains de producción contamine tus entornos de prueba. Si tu dominio principal es example.com, usá example-staging.com para staging y no staging.example.com. Es un poco más de laburo en DNS, pero te ahorra dolores de cabeza cuando el navegador de un tester se niega a cargar el ambiente de QA.

Errores comunes al configurar HSTS (más allá de los 5 principales)

No verificar que el certificado cubra todos los subdominios

Si activás includeSubDomains con un certificado que solo cubre el apex, los subdominios quedan inaccesibles aunque el DNS resuelva correctamente. Usá wildcards (*.example.com) o certificados SAN que incluyan explícitamente cada subdominio.

Olvidar el always en Nginx

En Nginx, add_header sin el modificador always no agrega el header en respuestas de error (4xx, 5xx). Si tu sitio devuelve un 500, el navegador no recibe HSTS y no refuerza la política. Siempre usá add_header ... always.

Asumir que el redirect 301 es suficiente

Un redirect HTTP 301 de HTTP a HTTPS no es lo mismo que HSTS. El redirect ocurre después de que el navegador hizo la solicitud en texto plano —un atacante puede interceptar esa primera solicitud. HSTS evita que esa primera solicitud en texto plano llegue a existir. Son capas complementarias, no intercambiables.

Preguntas Frecuentes

¿Qué errores comunes hay al configurar HSTS en producción?

Los cinco errores más frecuentes son: enviar el header por HTTP en lugar de HTTPS (la RFC 6797 obliga a que viaje por TLS), activar preload sin auditar todos los subdominios, duplicar el header entre el proxy inverso y el backend, usar subdominios de producción para desarrollo local, y no considerar que el max-age es un TTL deslizante que se renueva en cada visita.

¿Cómo evitar que HSTS bloquee subdominios internos?

No actives includeSubDomains ni preload hasta haber auditado todos los subdominios y confirmado que cada uno tiene un certificado TLS válido. Si tenés servicios internos como VPNs o dashboards que no pueden usar HTTPS, mantené el header solo en el apex (max-age=31536000 sin includeSubDomains) o usá dominios separados para esos servicios.

¿Por qué HSTS no funciona si lo envío por HTTP?

Según la RFC 6797, los navegadores ignoran cualquier header Strict-Transport-Security recibido por una conexión HTTP sin cifrar. El motivo es que un atacante activo podría modificar o inyectar headers en tráfico no cifrado. HSTS solo se registra cuando el header llega por una conexión TLS verificada (puerto 443).

¿Cómo desactivar HSTS en Chrome si ya está cacheado?

Abrí chrome://net-internals/#hsts en la barra de direcciones, buscá el dominio en el campo “Query HSTS/PKP domain” para confirmar que está cacheado, y luego usá el campo “Delete domain security policies” para eliminarlo. Esto borra la política solo en tu navegador. Para desactivarlo a nivel servidor, serví Strict-Transport-Security: max-age=0 por HTTPS.

¿Cuánto tarda en eliminarse un dominio de la lista de preload de HSTS?

Entre 6 y 12 semanas, dependiendo del ciclo de release de cada navegador. Chrome, Firefox, Safari y Edge actualizan sus listas de preload en versiones distintas y con cronogramas independientes. Una vez que solicitás la remoción en hstspreload.org, el dominio queda marcado para eliminación y se va propagando a medida que los navegadores publican nuevas builds.

Conclusión

HSTS es una de esas herramientas que parecen triviales hasta que te explotan en la cara. La diferencia entre una configuración correcta y un outage de semanas está en detalles que muchos pasan por alto: el header solo se registra por TLS, el preload es un compromiso a largo plazo, los proxies duplican headers sin avisar, y el max-age se renueva solo como un inquilino que no se quiere ir.

Si estás armando la infraestructura de un sitio nuevo, empezá con max-age bajos, auditá cada subdominio como si tu trabajo dependiera de eso (porque depende), y nunca, pero nunca, actives preload sin tener un inventario completo de lo que rompés. Para proyectos en Argentina, si necesitás hosting con soporte para HTTPS y certificados SSL sin vueltas, donweb.com tiene opciones que incluyen Let’s Encrypt integrado —te ahorra el dolor de cabeza de gestionar certificados a mano mientras configurás HSTS.

Fuentes

Te puede interesar...