Cómo funciona esta comprobación
Scanaris pide tu página principal como lo haría un navegador y lee las cabeceras de la respuesta. Busca seis cabeceras concretas y, para cada una que falta, abre un hallazgo con un valor recomendado: Content-Security-Policy, Strict-Transport-Security y X-Frame-Options con severidad media, y X-Content-Type-Options, Referrer-Policy y Permissions-Policy con severidad baja. No evalúa aquí la calidad de la CSP ni del HSTS: eso lo hacen los checks de CSP débil y HSTS débil. Solo se mira la respuesta de la URL escaneada, así que si tu API vive en otro dominio, escanéalo aparte.
Qué protege cada cabecera
- Content-Security-Policy limita de dónde pueden cargarse scripts, estilos e imágenes. Es la defensa principal contra la inyección de scripts (XSS).
- Strict-Transport-Security obliga al navegador a usar siempre HTTPS con tu dominio, aunque alguien escriba la dirección sin la ese.
- X-Frame-Options impide que tu web se incruste en un iframe ajeno, que es la base del clickjacking.
- X-Content-Type-Options: nosniff evita que el navegador "adivine" el tipo de un archivo y ejecute como script algo que no lo era.
- Referrer-Policy controla cuánta URL se envía a otros sitios cuando un usuario hace clic en un enlace.
- Permissions-Policy desactiva APIs del navegador que no usas, como cámara, micrófono o geolocalización.
Cómo añadirlas según tu hosting
Vercel
En vercel.json, o en next.config con la función headers() si usas Next.js:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains; preload" },
{ "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=()" }
]
}
]
}
Netlify
Un archivo _headers en la carpeta que se publica:
/*
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Nuxt
En nuxt.config, dentro de routeRules, la regla '/**' con un objeto headers y los mismos pares clave-valor. Es exactamente lo que hace Scanaris.
Express
import helmet from 'helmet';
app.use(helmet());
nginx
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" 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;
La Content-Security-Policy no está en los ejemplos a propósito: depende de qué scripts y servicios carga tu web y conviene empezarla en modo informe. El procedimiento está en cabeceras de seguridad HTTP explicadas para humanos.
Comprueba que están
curl -sI https://tudominio.com | grep -iE "strict-transport|x-frame|x-content-type|referrer-policy|permissions-policy|content-security"
Deben aparecer las seis líneas. Si usas una CDN delante del servidor, comprueba en la URL pública, porque algunas CDN quitan o sobrescriben cabeceras. El analizador de cabeceras hace la misma lectura con explicación por cabecera.
Preguntas frecuentes
¿X-Frame-Options o frame-ancestors?
Las dos hacen lo mismo; frame-ancestors dentro de la CSP es la versión moderna y permite listar dominios concretos. Mantén X-Frame-Options además para navegadores antiguos; no se estorban.
¿Puedo romper la web añadiendo estas cabeceras?
Las cinco de los ejemplos no rompen nada en una web normal. La única con riesgo es la CSP, por eso se añade en modo Content-Security-Policy-Report-Only primero y se pasa a bloquear cuando los informes están limpios.
¿Hace falta preload en HSTS?
No para pasar el check. preload permite incluir tu dominio en la lista que traen los navegadores de fábrica; es un compromiso a largo plazo (todo tu dominio y subdominios en HTTPS para siempre), así que actívalo solo cuando estés seguro.