Seguridad web

CSP (Content Security Policy)

Se lee en aproximadamente 4 minutos

Qué es CSP (Content Security Policy)

CSP (Content Security Policy) es un encabezado de respuesta HTTP que permite al servidor controlar las fuentes de los recursos (scripts, hojas de estilo, imágenes, fuentes, etc.) que una página web puede cargar. El navegador bloquea la carga o ejecución de recursos no permitidos por CSP, por lo que actúa como una capa que impide la ejecución de los scripts inyectados mediante XSS (Cross-Site Scripting) y el envío al exterior de la información robada.

La medida fundamental contra XSS es el escape de salida, pero las omisiones de implementación no se pueden eliminar por completo. CSP cumple el rol de defensa multicapa de "no permitir la ejecución del script del atacante incluso si existe una vulnerabilidad XSS". Aun así, lo único que puede detener son las cargas y ejecuciones no permitidas, de modo que los ataques que se llevan a cabo dentro de lo permitido no se bloquean. Entre los encabezados de seguridad es el que admite más elementos configurables, y hasta qué punto se ajusten determina directamente el efecto real. En cuanto a la especificación, el Level 2 pasó a ser Recomendación del W3C el 15 de diciembre de 2016, mientras que el Level 3 seguía en elaboración como Borrador de Trabajo del W3C en agosto de 2026.

Directivas principales

CSP se compone de múltiples directivas que especifican las fuentes permitidas para cada tipo de recurso.

  • default-src: Política predeterminada para recursos no especificados explícitamente por otras directivas. default-src 'self' permite solo recursos del mismo origen. El respaldo solo se aplica a las directivas de carga, de modo que base-uri, form-action y frame-ancestors siguen sin especificarse aunque se escriba default-src 'none', y hay que indicarlas una por una.
  • script-src: Controla las fuentes de carga de JavaScript. La directiva central para la protección contra XSS. Se recomienda evitar 'unsafe-inline' y usar nonce o hash. Según la especificación, en cuanto se especifica un nonce o un hash, 'unsafe-inline' se ignora, por lo que escribir ambos a la vez solo tiene sentido como compatibilidad con implementaciones antiguas que no interpretan el nonce.
  • style-src: Controla las fuentes de carga de CSS.
  • img-src: Controla las fuentes de carga de imágenes.
  • connect-src: Controla los destinos de conexión de fetch, XMLHttpRequest y WebSocket.
  • font-src: Controla las fuentes de carga de fuentes web.
  • frame-src: Controla de qué fuentes puede cargar páginas el iframe de la propia página (control del lado que incrusta).
  • frame-ancestors: Funciona en el sentido opuesto y controla los orígenes de las páginas padre que pueden incrustar el sitio en iframe (control del lado incrustado). Es el sucesor de X-Frame-Options, y es esta la directiva que se especifica como medida contra el clickjacking.

Métodos de especificación de valores de fuente

  • 'self': Mismo origen
  • 'none': Bloquear todo
  • 'nonce-{random}': Permitir solo scripts/estilos inline con un valor nonce específico
  • 'strict-dynamic': Permitir también los scripts cargados dinámicamente por scripts autorizados con nonce o hash. Al especificarlo, los dominios y esquemas enumerados en script-src, junto con 'self' y 'unsafe-inline', se ignoran al decidir si un script puede cargarse, y solo surten efecto el nonce y el hash
  • Dominios específicos: https://cdn.example.com

Pasos para una implementación gradual

La implementación de CSP debe realizarse gradualmente para no romper el sitio existente.

Paso 1: Monitoreo en modo Report-Only

Usando el encabezado Content-Security-Policy-Report-Only, solo se detectan y reportan las violaciones de política sin bloquear recursos. Primero, en este modo, se comprende qué recursos carga actualmente el sitio.

Paso 2: Elaboración de la política básica

Basándose en el análisis de los reportes, se van ajustando las fuentes empezando por las directivas de carga de imágenes, estilos y similares. En el caso de los scripts, un estudio de 2016 (Lukas Weichselbaum et al., "CSP Is Dead, Long Live CSP!") documentó que los endpoints JSONP o las redirecciones abiertas que quedan en dominios ya permitidos pueden convertirse en una vía para eludir la política, por lo que el diseño no debe apoyarse solo en enumerar las fuentes (lista blanca). La especificación de CSP Level 3 también menciona, a título informativo, que la configuración que combina nonce o hash con 'strict-dynamic' en script-src y ajusta base-uri se denomina Strict CSP y es una mitigación fácil de implementar.

Paso 3: Aplicación en producción y monitoreo continuo

Se cambia al encabezado Content-Security-Policy para la aplicación en producción. Se recopilan continuamente reportes de violaciones de política con la directiva report-to (el Level 3 marca report-uri como obsoleta e indica cómo sustituirla por la anterior) para responder a falsos positivos y nuevos requisitos de recursos. Durante la transición conviene escribir ambas, para no perder reportes en entornos que solo interpretan una de ellas.

Ejemplo de política estricta recomendada

default-src 'none'; script-src 'self' 'nonce-{random}' 'strict-dynamic'; style-src 'self' 'nonce-{random}'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'

Esta política controla los scripts inline con nonce y permite también los scripts cargados dinámicamente con 'strict-dynamic'. Si se necesita compatibilidad con navegadores que no interpretan 'strict-dynamic', las notas de la especificación describen la práctica de añadir además https: en script-src (los navegadores que sí lo interpretan lo ignoran).

Integración de CSP con otros encabezados de seguridad

Lo único que CSP puede juzgar es si un recurso se puede cargar y ejecutar. Al combinarlo con otros encabezados de seguridad, cada uno cubre el ámbito del que se encarga.

  • Combinación con HSTS: Forzar HTTPS. En una página transmitida por HTTP en texto claro, el propio encabezado CSP puede eliminarse o reescribirse durante el trayecto, así que HTTPS es lo que asegura una vía por la que la política llega intacta.
  • X-Content-Type-Options: nosniff: Prevenir el MIME type sniffing y bloquear la ejecución de recursos que no deberían interpretarse como scripts.
  • Relación con CORS: Ambos actúan en sentidos opuestos. CSP está del lado que limita desde qué fuentes puede cargar recursos la propia página, mientras que CORS está del lado que, según lo que declara el servidor, abre solo en la medida necesaria la lectura de respuestas que la política del mismo origen mantiene cerrada.

La parte laboriosa de la implementación consiste en inventariar uno por uno los scripts inline y las etiquetas de terceros que ya existen, y reescribirlos para que lleven nonce y para ordenar las fuentes. Ese inventario crece cuantos más años lleva el sitio en funcionamiento, de modo que si en un proyecto nuevo se adopta desde el principio una estructura de plantillas que presupone el nonce, después no hace falta añadir de forma retroactiva las medidas contra XSS y el clickjacking.

Para obtener más información sobre este tema, consulte Encabezados de seguridad HTTP - 5 encabezados esenciales para proteger tu sitio web.

Conceptos erróneos comunes

Si se configura CSP, las medidas contra XSS son innecesarias
CSP es una capa de defensa multicapa que mitiga el daño de XSS, no sustituye la medida fundamental contra XSS (escape de salida). Las técnicas para eludir las políticas que se apoyan en enumerar las fuentes (lista blanca) quedaron documentadas en un estudio de 2016 (Lukas Weichselbaum et al., "CSP Is Dead, Long Live CSP!"), y la especificación de CSP Level 3 recomienda la configuración que usa nonce o hash junto con 'strict-dynamic'. Implementar tanto el escape de salida como CSP es un requisito previo.
CSP es difícil de configurar, así que no es necesario para sitios pequeños
El riesgo de XSS existe incluso en sitios pequeños. Comenzar con una política mínima (ejemplo: default-src 'self'; script-src 'self') facilita la implementación. Se puede verificar el impacto con el modo Report-Only y hacer más estricta la política gradualmente.
Compartir

Términos relacionados

Artículos relacionados