HTTPS es solo el punto de partida
La mayoria de administradores de sitios web asumen que, una vez instalado el certificado TLS y activado HTTPS, su sitio esta protegido. Es un error comprensible: el candado verde en la barra del navegador transmite confianza. Pero HTTPS solo garantiza una cosa: que el trafico entre el navegador del visitante y tu servidor viaja cifrado. Nada mas.
HTTPS no impide que un atacante inyecte scripts maliciosos en tu pagina (XSS). No evita que tu web se cargue dentro de un iframe fraudulento (clickjacking). No controla que recursos externos pueden ejecutarse en el contexto de tu dominio. Y no limita que informacion sensible se filtra a traves de las cabeceras de referencia.
Para cubrir esos flancos existen las cabeceras de seguridad HTTP: directivas que tu servidor envia al navegador indicandole como debe comportarse al renderizar tu sitio. Son la segunda linea de defensa, y sin ellas, HTTPS ofrece una falsa sensacion de seguridad.
Las 6 cabeceras de seguridad imprescindibles
1. Strict-Transport-Security (HSTS)
Que hace: Indica al navegador que solo debe conectarse a tu dominio mediante HTTPS, incluso si el usuario escribe http:// manualmente. Ademas, impide que el usuario acepte certificados no validos.
Que ataque previene: SSL stripping, donde un atacante en la misma red intercepta la primera peticion HTTP (antes de la redireccion a HTTPS) y la mantiene en texto plano.
Configuracion correcta:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
El valor max-age=63072000 equivale a dos anos. includeSubDomains extiende la proteccion a todos los subdominios. preload permite que tu dominio se incluya en la lista de precarga de los navegadores, lo que elimina incluso la primera peticion insegura.
Error comun: Establecer un max-age demasiado corto (por ejemplo, 3600 segundos) o no incluir includeSubDomains, lo que deja los subdominios expuestos a ataques de degradacion de protocolo.
2. Content-Security-Policy (CSP)
Que hace: Define una lista blanca de origenes autorizados para cada tipo de recurso (scripts, estilos, imagenes, fuentes, iframes). El navegador bloquea cualquier recurso que no coincida con la politica declarada.
Que ataque previene: Cross-Site Scripting (XSS). Si un atacante consigue inyectar una etiqueta <script> que apunta a un dominio externo, CSP impide que el navegador la ejecute.
Configuracion correcta:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'
La directiva default-src 'self' restringe todo por defecto al mismo origen. Despues se abren excepciones especificas para cada tipo de recurso.
Error comun: Anadir 'unsafe-inline' o 'unsafe-eval' a script-src para que "deje de dar errores en consola". Esto anula practicamente toda la proteccion de CSP contra XSS, ya que permite la ejecucion de scripts en linea y la evaluacion dinamica de codigo.
3. X-Frame-Options
Que hace: Controla si tu pagina puede cargarse dentro de un <iframe>. Esto impide que un atacante muestre tu sitio en una capa invisible sobre otra pagina para capturar clics del usuario.
Que ataque previene: Clickjacking. El atacante superpone tu web (por ejemplo, un boton de "Confirmar pago") sobre una pagina aparentemente inofensiva, y el usuario hace clic sin saber que esta interactuando con tu sitio.
Configuracion correcta:
X-Frame-Options: DENY
Si tu sitio necesita ser embebido en iframes de tu propio dominio, usa SAMEORIGIN en lugar de DENY.
Error comun: Usar ALLOW-FROM https://ejemplo.com, que esta obsoleto y no es soportado por los navegadores modernos. Quien lo configura cree que esta protegido, pero la directiva se ignora silenciosamente.
4. X-Content-Type-Options
Que hace: Impide que el navegador "adivine" el tipo MIME de un recurso. Sin esta cabecera, un navegador puede interpretar un archivo de texto como JavaScript ejecutable si el contenido se lo parece.
Que ataque previene: MIME sniffing. Un atacante sube un archivo con extension .txt pero contenido JavaScript. Sin esta cabecera, el navegador podria ejecutarlo.
Configuracion correcta:
X-Content-Type-Options: nosniff
Solo tiene un valor posible. Es la cabecera mas sencilla de implementar y una de las mas olvidadas.
Error comun: Simplemente no configurarla. Muchos servidores no la incluyen por defecto, y al ser una cabecera "invisible" (no produce errores evidentes), pasa desapercibida durante meses o anos.
5. Referrer-Policy
Que hace: Controla que informacion se incluye en la cabecera Referer cuando un usuario navega desde tu sitio a otro. Puede contener la URL completa (incluyendo parametros con tokens, IDs de sesion u otros datos sensibles) o solo el origen.
Que ataque previene: Filtracion de datos sensibles a traves de la URL. Si tu pagina tiene parametros como ?token=abc123&email=user@ejemplo.com, un enlace externo recibiria toda esa informacion en la cabecera Referer.
Configuracion correcta:
Referrer-Policy: strict-origin-when-cross-origin
Esta politica envia la URL completa en navegacion dentro del mismo origen, pero solo el dominio (sin ruta ni parametros) en peticiones cross-origin. Es el equilibrio optimo entre privacidad y funcionalidad.
Error comun: Configurar no-referrer, que elimina por completo la cabecera. Aunque es la opcion mas restrictiva, rompe herramientas de analitica web y algunos flujos de autenticacion OAuth que dependen de la informacion de referencia.
6. Permissions-Policy
Que hace: Controla que APIs del navegador puede usar tu sitio: camara, microfono, geolocalizacion, pantalla completa, acelerometro, pagos y muchas mas. Permite desactivar funcionalidades que tu sitio no necesita.
Que ataque previene: Abuso de funcionalidades del navegador. Si un script inyectado intenta acceder a la camara o al microfono, Permissions-Policy lo bloqueara siempre que hayas desactivado esos permisos.
Configuracion correcta:
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
Los parentesis vacios () significan "ningun origen tiene permiso". Solo habilita las funcionalidades que tu aplicacion realmente necesita.
Error comun: No configurar esta cabecera en absoluto. Por defecto, cualquier script que se ejecute en tu pagina puede solicitar acceso a la camara, el microfono o la geolocalizacion del usuario.
Como verificar tus cabeceras
Puedes inspeccionar las cabeceras de respuesta manualmente desde las herramientas de desarrollo de cualquier navegador (pestana Network). Sin embargo, una verificacion puntual no garantiza que la configuracion se mantenga tras cada despliegue.
UareSafe evalua automaticamente los 8 controles de cabeceras de seguridad como parte de la dimension de Seguridad Tecnica (que representa el 30% de la puntuacion total). El analisis detecta cabeceras ausentes, valores inseguros y configuraciones obsoletas, generando un informe detallado con recomendaciones accionables.
Guia rapida de implementacion
Nginx
server {
listen 443 ssl;
server_name ejemplo.com;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
}
Next.js (next.config.js)
const securityHeaders = [
{ key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' },
{ key: 'Content-Security-Policy', value: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
];
module.exports = {
async headers() {
return [{ source: '/(.*)', headers: securityHeaders }];
},
};
Express
const helmet = require('helmet');
app.use(helmet());
// O manualmente:
app.use((req, res, next) => {
res.setHeader('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload');
res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self'");
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
next();
});
Conclusion
HTTPS es el suelo, no el techo. Cifrar el trafico es un requisito minimo, no una estrategia de seguridad completa. Las seis cabeceras descritas en este articulo se configuran en menos de 15 minutos y elevan drasticamente la postura de seguridad de cualquier sitio web.
No se trata de complicar la infraestructura. Se trata de decirle al navegador como debe proteger a tus usuarios. Si tu servidor no envia estas instrucciones, el navegador tomara las decisiones por defecto, y esas decisiones raramente priorizan la seguridad.
Configura las cabeceras. Verificalas con cada despliegue. Y si quieres una evaluacion automatizada y continua, UareSafe analiza tu sitio en las seis dimensiones de seguridad que importan, incluidas las cabeceras que acabamos de revisar.