AldeaCode Logo
Security Content Security Policy (CSP): Guía para Principiantes
Security AldeaCode Architecture

Content Security Policy (CSP): Guía para Principiantes

La cabecera Content Security Policy explicada para principiantes. Frena ataques XSS con strict-dynamic, nonces y las directivas que de verdad importan.

Qué hace CSP en realidad

Por defecto, el navegador ejecuta cualquier JavaScript que la página le pida ejecutar. Si un atacante consigue colar una etiqueta <script> en un campo de comentario, en un parámetro de URL o en una librería de terceros de la que dependes, el navegador lo ejecuta con los mismos privilegios que tu propio código.

Content Security Policy (CSP) es una cabecera HTTP que le dice al navegador: “solo ejecuta scripts de estos orígenes, solo envía datos a estos endpoints, solo carga imágenes desde estos sitios”. Lo que esté fuera de esa lista se bloquea, sin preguntas.

Es una lista de permisos para todo lo que la página puede hacer. La envías una vez en una cabecera y el navegador la aplica en cada petición.

El problema de los terceros

Cada SDK de analítica, widget de pago o chat que incrustas se ejecuta con acceso completo al DOM. Eso incluye el campo de la contraseña, el formulario de la tarjeta y las cookies. Si alguno de esos proveedores se ve comprometido (o simplemente decide portarse mal), puede leerlo todo.

CSP limita lo que esos scripts pueden hacer, incluso después de cargarse.

Por qué importa legalmente

CSP no es un adorno opcional. El Artículo 32 del RGPD exige “medidas técnicas y organizativas apropiadas” para cualquier sistema que maneje datos personales. Si tratas emails, nombres o números de tarjeta y un ataque XSS los exfiltra, el regulador preguntará por qué no había una cabecera CSP básica.

Un ataque tipo Magecart (donde se inyecta JS para robar datos de tarjetas en el checkout) es difícil de ejecutar contra un sitio con un connect-src y un script-src ajustados. Las multas del RGPD pueden llegar al 4% de la facturación global, pero el punto práctico es más sencillo: una cabecera que puedes desplegar en una tarde detiene uno de los patrones de exfiltración más comunes en la web.

Las directivas que importan

CSP funciona con directivas. Cada una controla una categoría de recurso. Estas son las que realmente necesitas conocer:

  1. default-src 'none': el punto de partida seguro. Bloquea todo y luego autoriza cosas concretas más abajo. Es agresivo, pero evita que se te olvide alguna categoría.
  2. script-src: de dónde puede venir el JavaScript. En 2026, olvida la lista larga de dominios de confianza. Usa un nonce o un hash en su lugar (más sobre esto abajo).
  3. connect-src: a dónde puede la página enviar datos vía fetch, XHR o WebSockets. Si un script malicioso intenta hacer POST de tu cookie de sesión a hacker.com, esta es la directiva que lo bloquea.
  4. img-src: limita desde dónde se cargan las imágenes. Útil contra píxeles de seguimiento y exploits de renderizado.
  5. frame-ancestors: quién puede embeber tu página en un iframe. Sustituye a la antigua cabecera X-Frame-Options y protege contra clickjacking.

Con eso cubres los patrones de ataque más comunes. Más adelante puedes añadir directivas adicionales (style-src, font-src, media-src), pero empezar con estas cinco te da casi toda la protección.

De las listas blancas a strict-dynamic

El método antiguo era una lista larga de dominios de confianza: https://www.google.com, https://cdn.jsdelivr.net, etc. Dos problemas con eso:

  1. Mantenimiento: un CDN cambia un subdominio y tu web se rompe.
  2. Bypass: si cualquier dominio de la lista aloja una librería vulnerable (piensa en ajax.googleapis.com con una versión antigua de AngularJS), un atacante puede cargar esa librería y saltarse tu CSP.

CSP Nivel 3 lo arregló con 'strict-dynamic'. La idea: autorizas un script con un nonce (un valor aleatorio que el servidor genera por petición y mete tanto en la cabecera como en la etiqueta del script). Cualquier script que ese script autorizado cargue también es de confianza. Cualquier script que el navegador vea sin un nonce válido se bloquea.

Eso significa que dejas de mantener una lista de dominios. Firmas un script de entrada y él arranca las herramientas de terceros que necesites. Menos configuración, menos despliegues rotos, más difícil de saltar.

Un caso real: British Airways, 2018

Un grupo Magecart inyectó 22 líneas de JavaScript en un script que BA usaba en sus páginas de checkout. Esas 22 líneas capturaban los datos del formulario de pago y los enviaban por POST a un servidor del atacante.

Una directiva connect-src 'self' habría bloqueado el POST. El navegador se habría negado a enviar los datos de la tarjeta a un dominio que no estaba en la lista. El ataque habría fallado en silencio.

La multa inicial del RGPD fue de 183 millones de libras. Luego se redujo, pero la lección sigue en pie: una sola cabecera habría detenido el paso de la exfiltración.

Extensiones de navegador maliciosas

A veces el código malo no viene de tu stack. Un usuario instala una extensión sospechosa de Chrome y esa extensión inyecta scripts en todas las páginas que visita, incluida la tuya. Una CSP estricta bloquea la ejecución de esos scripts inyectados, lo que protege al usuario incluso cuando el problema viene de su propio navegador.

Cómo desplegarlo sin romper producción

CSP puede romper cosas si la activas en frío. Dos pasos prácticos:

  1. Empieza en modo solo informe. Envía Content-Security-Policy-Report-Only en lugar de Content-Security-Policy. El navegador reportará las violaciones a un endpoint que tú indiques, pero no bloqueará nada. Mantenlo así una o dos semanas, mira qué salta, arregla los casos legítimos.
  2. Luego pasa a modo bloqueo. Cuando el log de informes esté limpio, cambia el nombre de la cabecera. Mantén un endpoint de reporte vivo para detectar nuevas violaciones cuando aparezcan.

Si un proveedor te dice que su script necesita 'unsafe-inline', cuestiónalo. La mayoría de SDKs modernos funcionan bien con nonces o carga asíncrona. Los hashes son una opción para scripts inline estáticos que controles. Para una pila de cabeceras más completa, combina CSP con HSTS para evitar el SSL stripping en la capa de transporte.

Preguntas frecuentes sobre CSP

Lo que hacemos

Webs honestas, sin atajos.

Ingeniería real y diseño cuidado. Si te ha gustado el post, hablemos del tuyo.

Hablemos →

Te puede interesar

Ver todos los artículos →