10 cabeceras de seguridad HTTP que toda app debería tener
Guía clara de las cabeceras de seguridad HTTP esenciales: qué hacen, qué riesgo corres si faltan y cómo arreglar tus headers de seguridad web con IA.
Lanzaste tu app, funciona, los usuarios entran. Pero hay una capa de seguridad que casi nadie revisa hasta que algo sale mal: las cabeceras de seguridad HTTP. Son instrucciones que tu servidor le manda al navegador en cada respuesta, diciéndole cómo comportarse para protegerte a ti y a tus usuarios.
Lo bueno: configurarlas no requiere reescribir tu app. Suele ser cuestión de añadir unas líneas en tu servidor, tu framework o tu CDN. Lo malo: si faltan, abres la puerta a ataques que ni notarás hasta que un atacante los aproveche.
En esta guía repasamos diez headers de seguridad web esenciales, una por una: qué hace cada una, qué arriesgas si no está, cómo se ve una buena configuración, cómo verificarla y la idea de pedirle el arreglo a tu IA (Claude, Cursor, lo que uses). Sin jerga de más y tuteando, como siempre.
Nota: los valores que mostramos son ejemplos razonables como punto de partida. Adáptalos a tu app y prueba antes de mandar a producción, sobre todo con Content-Security-Policy.
1. Content-Security-Policy (CSP)
Qué hace. Le dice al navegador desde qué orígenes puede cargar scripts, estilos, imágenes y otros recursos. Es tu mejor defensa contra ataques de Cross-Site Scripting (XSS): aunque alguien logre inyectar un <script> malicioso, el navegador se niega a ejecutarlo si no está en tu lista permitida.
Riesgo si falta. Sin CSP, cualquier script inyectado se ejecuta con todos los permisos. Un XSS puede robar sesiones, tokens y datos de tus usuarios.
Cómo se ve bien. Una política estricta que evite unsafe-inline siempre que puedas:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
Cómo verificarla. Abre las DevTools del navegador (pestaña Network), revisa los headers de respuesta de tu página, o consulta tu reporte en Pursecure.
Pídeselo a tu IA. "Genera una Content-Security-Policy estricta para mi app Next.js que use solo recursos propios y Google Fonts, sin unsafe-inline, y dime cómo añadirla en mi configuración."
2. Strict-Transport-Security (HSTS)
Qué hace. Obliga al navegador a conectarse a tu sitio solo por HTTPS durante un tiempo definido. Una vez que el navegador ve este header, ni siquiera intenta usar HTTP, aunque el usuario escriba http://.
Riesgo si falta. Un atacante en la misma red (un wifi público, por ejemplo) puede interceptar la primera conexión HTTP y hacer un ataque de tipo man-in-the-middle antes de que llegues a HTTPS.
Cómo se ve bien.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Eso es un año, aplicado a subdominios. Añade preload solo cuando estés seguro de que todo tu dominio sirve HTTPS.
Cómo verificarla. Mira los headers de tu sitio servido por HTTPS. Si max-age es muy bajo o el header no aparece, hay trabajo por hacer.
Pídeselo a tu IA. "Configura HSTS con un año de duración e includeSubDomains en mi servidor [tu stack], y explícame el riesgo de activar preload antes de tiempo."
3. X-Content-Type-Options
Qué hace. Con el valor nosniff, le dice al navegador que no adivine el tipo de un archivo. Respeta el Content-Type que tú declaras y nada más.
Riesgo si falta. El navegador podría interpretar un archivo subido por un usuario (que tú crees inofensivo) como un script ejecutable. Eso habilita ataques de tipo MIME sniffing.
Cómo se ve bien.
X-Content-Type-Options: nosniff
No hay matices: o está, o no está. Ponla siempre.
Cómo verificarla. Revisa que el header aparezca en las respuestas de tu app.
Pídeselo a tu IA. "Añade el header X-Content-Type-Options: nosniff a todas las respuestas de mi app en [tu framework]."
4. X-Frame-Options
Qué hace. Controla si tu sitio puede mostrarse dentro de un <iframe> en otra página. Previene el clickjacking, donde un atacante incrusta tu sitio en una página falsa y engaña al usuario para que haga clics sin saberlo.
Riesgo si falta. Tu pantalla de login o un botón de "confirmar pago" puede ser superpuesto de forma invisible en un sitio malicioso. El usuario cree que hace clic en una cosa y en realidad actúa sobre la tuya.
Cómo se ve bien.
X-Frame-Options: DENY
Para apps modernas, la opción frame-ancestors 'none' dentro de tu CSP cumple lo mismo y es más flexible. Tener ambas no estorba.
Cómo verificarla. Confirma que el header está presente, o que tu CSP incluye frame-ancestors.
Pídeselo a tu IA. "Protege mi app contra clickjacking con X-Frame-Options: DENY y la directiva frame-ancestors en mi CSP."
5. Referrer-Policy
Qué hace. Controla cuánta información sobre la URL de origen se envía cuando un usuario hace clic en un enlace que sale de tu sitio. Sin control, podrías estar filtrando rutas internas, IDs o tokens que viajan en la URL.
Riesgo si falta. Sitios externos y herramientas de analítica de terceros reciben tus URLs completas en el header Referer. Eso puede exponer datos sensibles que nunca quisiste compartir.
Cómo se ve bien.
Referrer-Policy: strict-origin-when-cross-origin
Manda la URL completa dentro de tu propio dominio, pero solo el origen (sin la ruta) cuando el destino es externo.
Cómo verificarla. Revisa el header en las respuestas; si no aparece, el navegador usa su valor por defecto, que no siempre es el más prudente.
Pídeselo a tu IA. "Configura Referrer-Policy: strict-origin-when-cross-origin en mi app y explícame qué datos deja de filtrarse."
6. Permissions-Policy
Qué hace. Decide qué funciones del navegador puede usar tu sitio: cámara, micrófono, geolocalización, sensores. Si tu app no necesita el micrófono, lo apagas, y de paso lo apagas para cualquier script de terceros o iframe incrustado.
Riesgo si falta. Un script comprometido o un iframe de un tercero podría pedir acceso a la cámara o la ubicación del usuario en tu nombre.
Cómo se ve bien. Deniega todo lo que no uses:
Permissions-Policy: camera=(), microphone=(), geolocation=(), browsing-topics=()
Si necesitas alguna función, la habilitas solo para tu propio origen, por ejemplo geolocation=(self).
Cómo verificarla. Confirma el header en tus respuestas y revisa que solo permita lo que tu app realmente necesita.
Pídeselo a tu IA. "Genera un header Permissions-Policy que desactive cámara, micrófono y geolocalización para mi app, que no usa ninguna de esas funciones."
7. Cookies con Secure, HttpOnly y SameSite
Qué hace. No es un header de respuesta general, sino tres atributos que pones en cada cookie sensible (como la de sesión):
- Secure: la cookie solo viaja por HTTPS.
- HttpOnly: JavaScript no puede leerla, así un XSS no roba tu sesión.
- SameSite: limita cuándo se envía la cookie en peticiones desde otros sitios; ayuda contra CSRF.
Riesgo si falta. Sin HttpOnly, un XSS puede leer la cookie de sesión y suplantar al usuario. Sin Secure, la cookie puede viajar en claro. Sin SameSite, quedas expuesto a ataques de tipo CSRF.
Cómo se ve bien.
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/
Usa SameSite=Strict si tu flujo lo permite; Lax es un buen equilibrio para la mayoría.
Cómo verificarla. En DevTools, pestaña Application/Storage, revisa que tus cookies de sesión tengan las tres marcas.
Pídeselo a tu IA. "Asegura que las cookies de sesión de mi app [tu stack] tengan Secure, HttpOnly y SameSite, y muéstrame el cambio exacto."
8. CORS bien configurado
Qué hace. CORS (Cross-Origin Resource Sharing) define qué orígenes externos pueden llamar a tu API desde el navegador. Es lo contrario de un header de bloqueo: si lo configuras mal y demasiado abierto, le das permiso a cualquiera.
Riesgo si falta o está mal. El error clásico es responder con Access-Control-Allow-Origin: * junto con Access-Control-Allow-Credentials: true, o reflejar cualquier origen que llegue. Eso permite que sitios maliciosos hagan peticiones autenticadas en nombre de tus usuarios.
Cómo se ve bien. Lista explícita de orígenes confiables, nunca un comodín cuando manejas credenciales:
Access-Control-Allow-Origin: https://app.tudominio.com
Access-Control-Allow-Credentials: true
Valida el origen contra una lista blanca en tu backend y responde solo a los que apruebas.
Cómo verificarla. Haz una petición desde un origen distinto y observa qué Access-Control-Allow-Origin responde tu API. Si refleja cualquier origen, hay un problema.
Pídeselo a tu IA. "Revisa mi configuración de CORS y cámbiala para que solo permita una lista blanca de orígenes, sin comodín cuando uso credenciales."
9. Redirecciones abiertas (open redirects)
Qué hace. No es un header, pero es un problema de seguridad web tan común que merece su lugar. Ocurre cuando tu app redirige a una URL que viene de un parámetro sin validar, por ejemplo ?next=https://sitio-malicioso.com.
Riesgo si falta el control. Un atacante manda un enlace que empieza en tu dominio (se ve confiable) y termina llevando al usuario a un sitio de phishing. Tu marca pone la confianza, el atacante pone la trampa.
Cómo se ve bien. Nunca redirijas a una URL arbitraria del usuario. Valida contra rutas internas o una lista de destinos permitidos:
// En vez de redirigir a req.query.next directamente:
const destinosPermitidos = ["/dashboard", "/perfil"];
const destino = destinosPermitidos.includes(next) ? next : "/dashboard";
Cómo verificarla. Busca en tu código dónde lees parámetros como next, redirect, url, return_to y confirma que cada uno se valida antes de usarlo en una redirección.
Pídeselo a tu IA. "Busca redirecciones abiertas en mi app: cualquier lugar donde redirija a una URL que venga de la petición sin validarla, y arréglalas con una lista blanca."
10. X-XSS-Protection y la actitud de "defensa en capas"
Qué hace. El viejo header X-XSS-Protection activaba un filtro del navegador contra XSS. Hoy los navegadores modernos lo ignoran o ya no lo soportan, y la recomendación es confiar en una buena CSP (cabecera número 1). Lo mencionamos para que sepas que verlo en guías antiguas no significa que debas depender de él.
La idea de fondo. Ninguna cabecera te salva sola. La seguridad real viene de combinarlas: CSP frena XSS, HSTS asegura el canal, las marcas de cookies protegen la sesión, CORS controla quién llama a tu API. Es defensa en capas.
Cómo se ve bien. Si lo usas por compatibilidad, déjalo en modo desactivado para evitar comportamientos raros:
X-XSS-Protection: 0
Y pon tu energía en una CSP sólida.
Pídeselo a tu IA. "Explícame por qué X-XSS-Protection está obsoleto y ayúdame a reemplazar su protección con una CSP bien hecha."
Qué revisar en tu sitio hoy
Si solo tienes diez minutos, haz esto:
- Abre las DevTools (pestaña Network), recarga tu sitio y haz clic en la primera petición. Mira la lista de Response Headers.
- Busca las imprescindibles:
Content-Security-Policy,Strict-Transport-Security,X-Content-Type-Options,X-Frame-Options,Referrer-PolicyyPermissions-Policy. Anota cuáles faltan. - Revisa tus cookies en la pestaña Application/Storage: ¿tu cookie de sesión tiene
Secure,HttpOnlyySameSite? - Prueba tu API desde otro origen y observa qué responde en CORS. Desconfía de cualquier comodín junto a credenciales.
- Busca en tu código parámetros de redirección (
next,redirect,url) y confirma que se validan.
Por cada hueco que encuentres, copia uno de los prompts de esta guía y pásaselo a tu IA con el nombre de tu stack. Vas a sorprenderte de lo rápido que se cierran.
Cierre: deja que Pursecure haga el inventario por ti
Revisar headers a mano funciona, pero es fácil olvidar uno o malinterpretar un valor. Para eso existe Pursecure: pegas la URL de tu sitio y en minutos recibes un puntaje de 0 a 100 con todos los hallazgos ordenados por gravedad, incluyendo cada una de las cabeceras de seguridad HTTP de esta guía.
Y lo mejor: cada hallazgo trae un prompt listo para arreglarlo con IA. No tienes que adivinar cómo configurar tu CSP o tus cookies: copias el prompt, lo pegas en Claude o Cursor, y aplicas el cambio. Sin alarmismo y sin teoría de más, directo a la solución.
Escanea tu sitio gratis en pursecure.app y descubre cuáles de estos diez headers de seguridad web te están faltando hoy.
Revisa la seguridad de tu sitio gratis
Pega tu URL y en segundos verás qué está exponiendo tu app, con el prompt listo para arreglarlo con tu IA.
Escanear gratis