← Volver al blog
SeguridadEquipo de Scanaris · 6 min de lectura · 04 de octubre de 2026

Las cabeceras de seguridad HTTP explicadas para humanos

Cuando lanzas una app con Cursor, Lovable o v0, el servidor responde a cada petición con una serie de cabeceras HTTP: instrucciones invisibles que el navegador obedece antes de pintar nada. Un puñado de ellas decide buena parte de la seguridad de tu web, y casi ninguna plantilla las trae activadas. Esta guía explica qué hace cada una, qué valor poner, los errores que rompen cosas y cómo configurarlas en Vercel, Next.js, Nuxt, Netlify, Cloudflare o nginx.

Qué es una cabecera y cómo ver las tuyas

Una cabecera es una línea de texto que acompaña a la respuesta, del tipo Nombre: valor. El navegador la lee y cambia su comportamiento: dejar o no cargar un script, forzar HTTPS, permitir o no que tu página se meta en un iframe. Puedes verlas en las herramientas de desarrollador (F12, pestaña Network, clic en el documento principal, apartado Response Headers) o desde la terminal:

curl -I https://tudominio.com

Si en esa lista no aparecen las de abajo, no están configuradas. No hay valores por defecto que te salven.

Las siete que importan

Content-Security-Policy (CSP)

Es la reina. Le dice al navegador de qué orígenes puede cargar scripts, estilos, imágenes, fuentes y conexiones. Si un atacante logra inyectar un <script> en tu página, una CSP bien puesta impide que se ejecute. Un punto de partida honesto para una app moderna:

Content-Security-Policy: default-src 'self'; script-src 'self' https://js.stripe.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://*.supabase.co; frame-ancestors 'none'; base-uri 'self'; form-action 'self'

El error típico es poner 'unsafe-inline' en script-src porque "si no, no funciona": eso tira por tierra la protección principal. Los frameworks modernos resuelven los scripts inline con un nonce (un valor aleatorio por petición) o con hashes. Y la forma segura de empezar es en modo informe: la cabecera Content-Security-Policy-Report-Only no bloquea nada, solo te cuenta qué bloquearía. Déjala así unos días, revisa los informes y pásala a la cabecera real cuando no rompa nada.

Strict-Transport-Security (HSTS)

Obliga al navegador a usar HTTPS durante el tiempo indicado, aunque el usuario escriba http:// o pulse un enlace antiguo. Evita que alguien en la misma red degrade la conexión. El valor habitual:

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

Actívala solo cuando todo tu dominio y sus subdominios vayan por HTTPS: si la pones con un subdominio en HTTP, lo dejas inaccesible durante un año en los navegadores que la hayan visto. Empieza con un max-age corto si tienes dudas.

X-Frame-Options y frame-ancestors

Impiden que tu web se cargue dentro de un <iframe> de otra página. Sin esto, alguien puede incrustar tu app en un sitio falso y engañar a los usuarios para que pulsen donde no deben: es el clickjacking. X-Frame-Options: DENY o SAMEORIGIN lo resuelve en navegadores antiguos; la versión moderna es la directiva frame-ancestors dentro de la CSP. Pon las dos.

X-Content-Type-Options

Un solo valor: nosniff. Impide que el navegador adivine el tipo de un archivo y ejecute como script algo que serviste como texto o imagen. Es una línea; no tiene excusa para faltar.

Referrer-Policy

Controla cuánta información de la URL de origen se envía al navegar a otro sitio o cargar un recurso externo. Sin control, puedes filtrar rutas privadas o tokens que viajan en la URL. strict-origin-when-cross-origin es el equilibrio sensato: tu dominio sí, la ruta completa no.

Permissions-Policy

Declara qué capacidades del navegador puede usar tu página y sus iframes: cámara, micrófono, geolocalización, pagos. Si no las usas, desactívalas; así un script inyectado o un iframe de terceros tampoco puede. Por ejemplo: camera=(), microphone=(), geolocation=().

Cross-Origin-Opener-Policy

Menos conocida: aísla tu ventana de las que la abrieron o que abriste con window.open, lo que corta una familia de ataques entre pestañas. same-origin es el valor habitual, salvo que dependas de ventanas emergentes de terceros (algunos logins con OAuth), donde conviene same-origin-allow-popups.

Las que conviene quitar

X-Powered-By y una cabecera Server con versión anuncian tu stack exacto a quien busque fallos conocidos. En Next.js se quita con poweredByHeader: false; en Express, con app.disable('x-powered-by'). Y X-XSS-Protection está obsoleta: los navegadores modernos la ignoran y en los antiguos llegó a causar fallos. No la pongas, o ponla a 0.

Cómo ponerlas según tu hosting

Vercel, para cualquier framework, en vercel.json:

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" },
        { "key": "X-Frame-Options", "value": "SAMEORIGIN" },
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
        { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
      ]
    }
  ]
}

Next.js: la función headers() de next.config.js, con la misma lista; la CSP con nonce se genera en el middleware. Nuxt: routeRules en nuxt.config.ts con un objeto headers, o un plugin de servidor si necesitas nonce. Netlify: un archivo _headers en la carpeta publicada:

/*
  Strict-Transport-Security: max-age=31536000; includeSubDomains
  X-Frame-Options: SAMEORIGIN
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin

Cloudflare: reglas de transformación de cabeceras de respuesta en el panel, sin tocar código. nginx en un VPS:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

La CSP la dejo fuera de estos bloques a propósito: es la única que depende de qué scripts y servicios usa tu app, y conviene construirla en modo informe antes de fijarla.

Errores que rompen cosas

  • HSTS antes de tener todo en HTTPS. Deja fuera a quien tenga un subdominio en HTTP. Verifica primero, activa después.
  • CSP sin nonce en Next.js o Nuxt. Ambos inyectan scripts inline para hidratar la página; sin nonce, la CSP estricta los bloquea y la app queda en blanco. Usa el mecanismo de nonce del framework.
  • Cabeceras solo en el HTML. Las rutas de API y los archivos estáticos también las necesitan, sobre todo nosniff. Aplica la regla a /(.*).
  • Cabeceras duplicadas. Si el CDN y la app añaden la misma, el navegador puede quedarse con la más restrictiva o ignorar ambas. Decide un sitio.
  • Olvidar los subdominios (app., api., docs.): cada uno responde con sus propias cabeceras.

Compruébalas desde fuera

Estas cabeceras son información pública: cualquiera puede leerlas, incluido tú. El verificador gratuito de cabeceras te lista las que faltan y las que están mal en segundos. Y Scanaris hace la comprobación completa de solo lectura, con unas 45 cosas más, y por cada cabecera ausente te da un fix prompt listo para pegar en tu IA con la línea exacta para tu hosting. No explota nada ni toca tu servidor: lee y te dice qué activar. Si quieres el contexto completo, está en la guía de seguridad para apps hechas con IA y en la checklist de lanzamiento.

Preguntas frecuentes

¿Las cabeceras hacen más lenta la web?

No. Son unos cientos de bytes por respuesta y el navegador las procesa en microsegundos. HSTS incluso la acelera, porque evita la redirección de HTTP a HTTPS en visitas posteriores.

¿Qué pasa si una cabecera rompe algo en producción?

Quítala o relájala y vuelve a desplegar: el efecto es inmediato, salvo HSTS, que los navegadores recuerdan durante el max-age. Por eso la CSP se prueba en modo informe y HSTS se activa al final.

¿Necesito CSP si mi app es pequeña?

Si tu app tiene un formulario o muestra contenido de usuarios, sí: es la defensa que convierte un XSS en un incidente menor. Empieza con el resto de cabeceras, que son triviales, y añade la CSP en modo informe cuando puedas dedicarle una tarde.

¿Y tu web, cómo va?

Pásale Scanaris y compruébalo en 30 segundos, gratis.

Escanear mi web

Checks relacionados