Cada respuesta de tu sitio lleva cabeceras HTTP (también llamadas encabezados) que el visitante nunca ve. Algunas son instrucciones de seguridad para el navegador: carga scripts solo desde estos orígenes, usa HTTPS con este dominio, no dejes que otros sitios muestren esta página dentro de un marco, no dejes que JavaScript lea esta cookie. Si faltan, el navegador aplica sus valores por defecto, más permisivos. Si están mal configuradas, pueden romper el inicio de sesión o el pago.
Esta guía explica cómo leer las cabeceras que tu sitio envía de verdad, qué hace cada una y qué valores son seguros para empezar. Incluye una configuración base para nginx, para Apache con .htaccess y para hostings estáticos como Cloudflare Pages y Netlify, además de los errores que dejan algunas respuestas sin cabeceras. Todos los ejemplos usan example.com.
Alcance de esta guía
El snapshot gratuito lee las cabeceras de una sola respuesta: la página de inicio del origen que escribes, tras seguir hasta cinco redirecciones. Sobre todo comprueba si cada cabecera está presente, no si sus valores encajan con tu sitio, y no es un pentest.
1. Comprueba tus cabeceras tú mismo: DevTools y curl
En Chrome o Edge, abre DevTools, selecciona el panel Network y recarga la página. Haz clic en la primera petición (el documento HTML), abre la pestaña Headers y baja hasta Response Headers. Marca Preserve log para conservar las peticiones entre cargas y redirecciones, y Disable cache para recibir una respuesta nueva en lugar de una guardada en caché (referencia del panel Network de Chrome DevTools). Si tienes DevTools en español, estas opciones aparecen traducidas. El Monitor de red de Firefox funciona igual.
Desde una terminal, curl muestra exactamente lo que envía el servidor:
curl -sS -D - -o /dev/null https://example.com/Añade -L para seguir las redirecciones y ver las cabeceras de cada salto. En Windows, llama a curl.exe y usa -o NUL. curl -I es más corto, pero envía una petición HEAD en lugar de GET, y algunas aplicaciones tratan HEAD por otra ruta de código, así que confirma lo que encuentres con un GET.
Repite la comprobación con la dirección http:// (debería responder con una redirección 301 o 308 a HTTPS), con el otro nombre de host (www o el dominio sin www), con una página que no existe, una página de inicio de sesión, una respuesta de la API y un archivo estático. La aplicación, el servidor web y la CDN suelen poner cabeceras distintas en cada uno, y solo cuenta lo que llega al navegador.
2. Qué hace cada cabecera y un valor seguro para empezar
| Cabecera | Qué hace | Valor inicial seguro |
|---|---|---|
| Content-Security-Policy | Limita desde dónde se pueden cargar scripts, estilos, marcos y otros recursos | Una política en borrador, enviada primero como Content-Security-Policy-Report-Only |
| CSP frame-ancestors | Decide qué sitios pueden incrustar la página en un marco (defensa contra el clickjacking) | frame-ancestors 'self' o 'none' |
| X-Frame-Options | Control de marcos antiguo, que se mantiene como respaldo para navegadores viejos | SAMEORIGIN o DENY, coherente con frame-ancestors |
| Strict-Transport-Security | Indica al navegador que use solo HTTPS con este host durante max-age segundos | max-age=300, que se sube por etapas |
| X-Content-Type-Options | Impide que el navegador adivine el tipo MIME; bloquea scripts y hojas de estilo servidos con un tipo incorrecto | nosniff |
| Referrer-Policy | Controla qué parte de la URL de la página se envía a otros sitios en la cabecera Referer | strict-origin-when-cross-origin |
| Permissions-Policy | Desactiva funciones del navegador, como la cámara, para la página y sus marcos | camera=(), microphone=(), geolocation=() |
| Cross-Origin-Opener-Policy | Aísla tu ventana de las ventanas emergentes de otros orígenes y de la página que la abrió | same-origin, o same-origin-allow-popups si usas ventanas emergentes de OAuth o de pago |
| Atributos de Set-Cookie | Limitan cómo viajan las cookies de sesión y quién puede leerlas | Secure; HttpOnly; SameSite=Lax |
| X-XSS-Protection | Controlaba un filtro de navegadores antiguos; hoy está obsoleta | Elimínala o envía 0 |
Con nosniff, el navegador se fía del Content-Type declarado y bloquea los scripts y las hojas de estilo que llegan con un tipo incorrecto, así que revisa esos tipos antes de activarlo. Sin cabecera Referrer-Policy, los navegadores actuales ya aplican strict-origin-when-cross-origin; OWASP sigue recomendando enviarla de forma explícita por los navegadores antiguos, y no-referrer es más estricta si nada de lo que usas necesita el referrer. En Permissions-Policy, () desactiva la función en la página y en todos los marcos que contiene; permítela solo para el origen del widget que la necesita. COOP same-origin ayuda contra los ataques de filtración entre orígenes (XS-Leaks), pero puede romper las ventanas emergentes de inicio de sesión o de pago servidas desde otro origen.
3. Content-Security-Policy y frame-ancestors
CSP le dice al navegador desde dónde puede cargar una página scripts, estilos, imágenes, marcos y conexiones. Limita lo que puede hacer un script inyectado; no sustituye al escapado y la validación de las entradas. La guía de CSP de MDN recomienda una CSP estricta basada en un nonce nuevo en cada respuesta, o en hashes, en lugar de una larga lista de hosts permitidos. 'unsafe-inline' anula buena parte de su utilidad, y el navegador lo ignora en cualquier directiva que también contenga un nonce o un hash. Lo que suele complicar una política estricta es el código de terceros que carga más scripts, como los gestores de etiquetas y los chats de atención al cliente, así que anota el motivo de cada excepción que añadas.
default-src sirve de respaldo para directivas de carga como script-src, pero no para frame-ancestors: una política default-src 'none' sigue permitiendo que cualquier sitio incruste la página. Define frame-ancestors 'self' de forma explícita, o 'none', que equivale aproximadamente a X-Frame-Options: DENY (MDN). La OWASP HTTP Headers Cheat Sheet indica que frame-ancestors deja obsoleta X-Frame-Options en los navegadores que la admiten, mientras que X-Frame-Options sigue cubriendo los antiguos; si envías las dos, haz que permitan lo mismo. Dos trampas: frame-ancestors, una política report-only y X-Frame-Options no tienen efecto dentro de una etiqueta <meta>, y X-Frame-Options: ALLOW-FROM hace que los navegadores modernos ignoren toda la cabecera.
Un primer borrador para un sitio sin scripts de terceros es la política recomendada por el OWASP Secure Headers Project:
default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requestsBloquea los scripts y estilos en línea y todo lo que se cargue desde otros hosts, así que al principio verás muchos informes; por eso empieza como Report-Only (apartado 8). Copia solo la línea de CSP: el conjunto completo del proyecto incluye también valores como Cache-Control: no-store y Clear-Site-Data, que desactivarían la caché y borrarían las cookies y los datos guardados del visitante en cada respuesta. En las respuestas JSON de una API, que el navegador no muestra como página, CSP aporta poco.
4. HSTS: sube max-age por etapas y piénsalo dos veces antes de usar preload
Strict-Transport-Security indica al navegador que use solo HTTPS con el host y que convierta automáticamente en HTTPS las peticiones http:// posteriores. Como recuerda la página de MDN en español, el navegador ignora la cabecera cuando llega por HTTP, así que envíala en las respuestas HTTPS, no en la redirección de HTTP a HTTPS. Por sí sola no puede proteger la primera conexión de un visitante.
Ten en cuenta el coste: en un host con HSTS, los visitantes no pueden saltarse los errores de certificado, así que un certificado caducado deja fuera a quien ya había visitado el sitio. Los certificados TLS públicos emitidos desde el 15 de marzo de 2026 pueden tener una validez máxima de 200 días (CA/Browser Forum), y Let's Encrypt ya no envía avisos de caducidad por correo, así que primero deja automatizada la renovación y monta tu propia vigilancia de caducidad. La guía de TLS y cabeceras HTTP trata la parte de los certificados.
Sube max-age (en segundos) por etapas, como recomienda hstspreload.org, y comprueba en cada paso que nada se rompe: 300 (5 minutos), 604800 (1 semana), 2592000 (1 mes) y después 31536000 (1 año) o 63072000 (2 años, el valor que usa OWASP). max-age=0 elimina la política, pero solo si se envía por HTTPS y solo para los visitantes que vuelven y la reciben. Añade includeSubDomains cuando todos los subdominios funcionen por HTTPS, y haz que cada subdominio envíe también su propia cabecera.
Preload incorpora tu dominio a los navegadores para que incluso la primera visita use HTTPS. El sitio de inscripción, hstspreload.org, recomienda hoy HSTS pero no la precarga: Chrome y Safari ya convierten a HTTPS las navegaciones HTTP, así que la precarga aporta poco, y una baja de la lista tarda meses en llegar a los usuarios. La OWASP HTTP Headers Cheat Sheet todavía incluye preload en su ejemplo, mientras que el valor recomendado por el OWASP Secure Headers Project lo omite. No lo añadas por defecto ni lo copies de una plantilla.
6. Cabeceras que sobran: X-XSS-Protection y otros restos
- X-XSS-Protection activaba en navegadores antiguos un filtro que podía crear por sí mismo vulnerabilidades XSS (MDN). OWASP aconseja no enviarla, o desactivarla con
0; CSP es su sustituto. - Expect-CT: OWASP dice que no se use y, citando a Mozilla, que se elimine de las configuraciones existentes.
- Public-Key-Pins (HPKP) se eliminó de Chromium en 2018 y ningún navegador moderno la admite.
- Feature-Policy ha sido sustituida por Permissions-Policy.
Server y X-Powered-By dicen qué software usas, a veces con número de versión. OWASP sugiere eliminarlas o hacer que no den información, pero su propia guía de pruebas lo llama seguridad por oscuridad, y MDN dice que mantener el software actualizado importa más. Quita los números de versión (en nginx, server_tokens off; elimina la versión, no la cabecera) y dedica el esfuerzo a las actualizaciones.
7. Una base para copiar: nginx, Apache (.htaccess) y hostings estáticos
Esta base para nginx define las cabeceras de bajo riesgo, empieza HSTS y CSP en su fase de prueba y redirige HTTP a HTTPS en el mismo host. El parámetro always añade las cabeceras también a las respuestas de error.
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
# aquí van ssl_certificate y ssl_certificate_key
server_tokens off;
add_header Strict-Transport-Security "max-age=300" 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;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'" always;
}Dos comportamientos documentados del módulo de cabeceras de nginx explican muchas cabeceras que faltan. Sin always, add_header solo se aplica a los códigos de estado 200, 201, 204, 206, 301, 302, 303, 304, 307 y 308, así que las páginas 404 y 500 salen sin las cabeceras. Y las directivas add_header se heredan del nivel superior solo si el nivel actual no define ninguna: un único add_header dentro de un bloque location elimina ahí todas las cabeceras de seguridad definidas a nivel de servidor. Repite las cabeceras, incluye un archivo común con include o, desde nginx 1.29.3, usa add_header_inherit merge;.
Si tu sitio está en un hosting con Apache y no tienes acceso a la configuración del servidor, puedes añadir las cabeceras en el archivo .htaccess con el módulo mod_headers:
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Content-Security-Policy-Report-Only "default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'"Según la documentación de Apache, con always las cabeceras se añaden también a las respuestas de error y a las redirecciones que genera el propio servidor. El módulo tiene que estar activo y el hosting tiene que permitir esta directiva en .htaccess (pertenece al grupo FileInfo de AllowOverride). Guarda una copia del archivo antes de editarlo y comprueba el resultado con curl.
Los hostings estáticos como Cloudflare Pages y Netlify leen un archivo _headers que se publica junto con el sitio. Este ejemplo sigue el formato documentado por Cloudflare, que Netlify también usa:
/*
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
X-Frame-Options: SAMEORIGIN
Content-Security-Policy-Report-Only: default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'Conoce sus límites. Cloudflare Pages no aplica el archivo a las respuestas generadas por Pages Functions, admite hasta 100 reglas de cabeceras con un máximo de 2000 caracteres por línea y une los valores con una coma cuando la misma cabecera se aplica dos veces. Netlify aplica las cabeceras personalizadas solo a los archivos que sirve él mismo, no al contenido que pasa por un proxy, a las funciones, a las edge functions ni a las páginas renderizadas en el servidor; esas respuestas tienen que definir sus propias cabeceras. HSTS no está en los ejemplos de Apache y de hosting estático: comprueba con curl qué envía ya la plataforma antes de añadirlo.
8. Despliega por etapas y evita los errores habituales
- Añade nosniff, Referrer-Policy, Permissions-Policy y la protección contra marcos, y prueba después el inicio de sesión, el pago y los widgets incrustados.
- Envía la CSP en borrador como
Content-Security-Policy-Report-Only. No se bloquea nada; las infracciones aparecen en la consola del navegador y, si la política indica un endpoint de informes, también allí. Recorre los flujos clave, incluidas las páginas que requieren inicio de sesión, y ajusta la política. - Empieza HSTS con un
max-agecorto y súbelo por etapas. - Aplica la CSP. Puede convivir con una política Report-Only más estricta para probar el siguiente ajuste.
- Repite las comprobaciones con curl después de cada cambio en el servidor, la CDN o el framework.
Errores habituales:
- Cabeceras solo en algunas respuestas. La página de inicio las tiene; la página 404, la API, los archivos estáticos o una página de acceso servida aparte, no.
- Cambiar de host y de esquema en una sola redirección. Si
http://example.comredirige directamente ahttps://www.example.com, el navegador nunca recibe HSTS paraexample.com. Redirige primero a HTTPS en el mismo host, envía HSTS en esa respuesta HTTPS y solo después redirige awww. - La CDN sobrescribe al origen. Una CDN o un proxy puede añadir, sustituir, quitar o duplicar cabeceras. Decide qué capa se encarga de cada cabecera y confirma el resultado con curl.
- Una CSP que lo permite todo. Una política llena de
'unsafe-inline','unsafe-eval'o*para acallar errores pasa una comprobación de presencia, pero bloquea poco. - includeSubDomains demasiado pronto. Un subdominio olvidado que solo funciona por HTTP deja de estar accesible para los navegadores que han guardado la política.
Las cabeceras son una capa más. La checklist de seguridad antes de lanzar una web las sitúa junto al DNS, TLS y las redirecciones, y la guía de auditoría de seguridad web cubre el inicio de sesión, los permisos y una rutina de revisión que se puede repetir.
9. Cómo revisa las cabeceras el snapshot gratuito de Sitelemetry
El snapshot gratuito de Sitelemetry ejecuta ocho comprobaciones pasivas sobre un origen público, sin registro; una de ellas lee las cabeceras de seguridad HTTP. No es un pentest ni la auditoría de seis áreas.
- Solicita la página de inicio del origen que escribes (descarta rutas y parámetros de consulta), sigue hasta cinco redirecciones y evalúa la respuesta final. No solicita otras páginas.
- Sobre todo comprueba la presencia. La falta de CSP, la falta de HSTS en un destino HTTPS, la ausencia de protección contra marcos y
Access-Control-Allow-Origin: *se califican como riesgo medio. Un X-Content-Type-Options distinto denosniff, la falta de Referrer-Policy y cualquier cabeceraServeroX-Powered-Byse califican como riesgo bajo, así queServer: nginxsin versión también genera una señal baja. Las cookies que esa respuesta establece sin HttpOnly, o sin Secure en HTTPS, se califican como riesgo medio; SameSite no se comprueba. - Una calificación aparte, Refuerzo (de la A a la F), puntúa las cabeceras presentes junto con el resultado de TLS, y da menos crédito a una CSP que permite
'unsafe-inline'(o'unsafe-eval'para scripts). Permissions-Policy y COOP solo cuentan en esta calificación. - La comprobación de redirección HTTPS depende de lo que escribas. Con un dominio sin esquema o una dirección
https://, marca como riesgo bajo unmax-agede HSTS inferior a 180 días, algo esperable durante la subida por etapas, y busca referenciashttp://en el HTML de la página (contenido mixto); no prueba la redirección de HTTP a HTTPS. La redirección solo se prueba si escribes la direcciónhttp://, y esa ejecución omite la comprobación de TLS y no informa de la falta de HSTS.
El resultado muestra una puntuación, la calificación de Refuerzo, el número de señales de riesgo y de controles aprobados, y hasta tres señales, primero los riesgos. No lista cada cabecera con su valor, así que usa DevTools o curl para eso y para las respuestas que el snapshot no solicita.
Preguntas frecuentes
¿Cómo compruebo las cabeceras de seguridad de mi web?
En las DevTools del navegador, abre el panel Network, recarga la página, selecciona el documento HTML y lee Response Headers. En una terminal, curl -sS -D - -o /dev/null https://example.com/ las muestra. Revisa también la dirección http://, una página 404, una respuesta de la API y un archivo estático, porque sus cabeceras suelen ser distintas.
¿Qué cabeceras de seguridad HTTP conviene configurar primero?
Empieza por X-Content-Type-Options: nosniff, Referrer-Policy, Permissions-Policy y la protección contra marcos, que son las que menos probabilidades tienen de romper algo; aun así, prueba después los scripts, el inicio de sesión y los widgets incrustados. Luego prueba una Content-Security-Policy en modo Report-Only y sube el max-age de HSTS por etapas.
¿Debo seguir enviando X-XSS-Protection?
No. Elimínala o envía X-XSS-Protection: 0, y apóyate en una Content-Security-Policy. El antiguo filtro del navegador que controlaba podía crear por sí mismo vulnerabilidades XSS.
¿Necesito X-Frame-Options si ya uso frame-ancestors?
La directiva frame-ancestors de CSP la sustituye en los navegadores que la admiten. X-Frame-Options: DENY o SAMEORIGIN sigue siendo un respaldo razonable para navegadores antiguos, siempre que las dos cabeceras permitan lo mismo. No uses ALLOW-FROM: los navegadores modernos ignoran toda la cabecera cuando lo encuentran.
¿Debo añadir mi dominio a la lista de precarga HSTS?
Normalmente no. El sitio de inscripción, hstspreload.org, recomienda hoy HSTS pero no la precarga, porque Chrome y Safari ya convierten a HTTPS las navegaciones HTTP. Además, una baja de la lista tarda meses en llegar a los usuarios.
¿Las cabeceras de seguridad hacen que mi sitio sea seguro?
No por sí solas. Limitan el daño de los scripts inyectados, el clickjacking, la degradación de protocolo y el robo de cookies. No corrigen código vulnerable, software desactualizado ni un control de acceso débil.
Fuentes y lecturas
- MDN: guía de Content Security Policy (CSP)developer.mozilla.org
- MDN: directiva CSP frame-ancestorsdeveloper.mozilla.org
- MDN (en español): cabecera Strict-Transport-Securitydeveloper.mozilla.org
- MDN: cabecera Set-Cookie y atributos de las cookiesdeveloper.mozilla.org
- OWASP HTTP Headers Cheat Sheetcheatsheetseries.owasp.org
- OWASP Secure Headers Project: valores de cabecera recomendadosraw.githubusercontent.com
- HSTS Preload List Submissionhstspreload.org
- nginx: módulo ngx_http_headers_module (add_header)nginx.org
- Apache HTTP Server 2.4: módulo mod_headershttpd.apache.org
- Cloudflare Pages: cabecerasdevelopers.cloudflare.com
- Netlify: cabeceras personalizadasdocs.netlify.com
Preparado por el equipo editorial de Sitelemetry. Consulta las fuentes enlazadas para profundizar.



