Content Security Policy (CSP) es probablemente el header de seguridad más potente — y el más incomprendido. Una CSP bien configurada elimina la inmensa mayoría de ataques XSS. Mal configurada, puede romper tu sitio entero o dar una falsa sensación de seguridad.
¿Qué hace CSP?
CSP le dice al navegador qué recursos tiene permitido cargar en tu página y desde qué orígenes. Si un atacante inyecta un script malicioso, el navegador lo bloquea porque no está en la lista autorizada.
Sin CSP, el navegador ejecuta cualquier script que encuentre en el DOM, sin importar su origen. Con CSP, solo ejecuta los que tú has autorizado explícitamente.
Las directivas principales
default-src
Política por defecto para todas las directivas no especificadas:
default-src 'self'
Significa: por defecto, solo carga recursos del mismo dominio.
script-src
Controla de dónde se pueden cargar scripts:
script-src 'self' https://cdn.example.com
Valores especiales:
'self': mismo origen'unsafe-inline': permite scripts inline (debilita significativamente la CSP)'nonce-{valor}': permite scripts con un nonce específico (recomendado)'strict-dynamic': confía en scripts cargados por scripts ya autorizados
Importante: nunca uses directivas que permitan la ejecución de código arbitrario. Son extremadamente peligrosas y anulan la protección CSP contra XSS.
style-src
Controla hojas de estilo:
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com
'unsafe-inline' para estilos es más aceptable que para scripts (menor riesgo de seguridad), pero los nonces son preferibles.
img-src
Controla imágenes:
img-src 'self' data: https:
data: permite imágenes base64 inline. https: permite cualquier imagen por HTTPS.
connect-src
Controla peticiones AJAX, WebSocket y EventSource:
connect-src 'self' https://api.example.com wss://ws.example.com
font-src
Controla fuentes:
font-src 'self' https://fonts.gstatic.com
frame-src
Controla iframes embebidos:
frame-src 'self' https://www.youtube.com
frame-ancestors
Controla quién puede embeber tu sitio en un iframe (reemplaza X-Frame-Options):
frame-ancestors 'none'
object-src
Controla plugins (Flash, Java, etc.):
object-src 'none'
Siempre 'none' salvo que tengas una razón muy específica.
Niveles de CSP
Nivel 1: CSP básica (mejor que nada)
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; object-src 'none'; frame-ancestors 'self'
Protección limitada contra XSS por unsafe-inline, pero bloquea la mayoría de recursos externos no autorizados.
Nivel 2: CSP con nonces (recomendado)
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{RANDOM}'; style-src 'self' 'nonce-{RANDOM}'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https://api.example.com; object-src 'none'; frame-ancestors 'none'
Cada script y estilo inline debe incluir el nonce correspondiente:
<script nonce="{RANDOM}">
// Script autorizado
</script>
El nonce se regenera en cada petición. Un atacante no puede predecirlo.
Nivel 3: CSP estricta (máxima seguridad)
Content-Security-Policy: default-src 'none'; script-src 'self' 'strict-dynamic' 'nonce-{RANDOM}'; style-src 'self' 'nonce-{RANDOM}'; img-src 'self'; font-src 'self'; connect-src 'self'; base-uri 'self'; form-action 'self'; object-src 'none'; frame-ancestors 'none'
default-src 'none' bloquea todo por defecto. Solo lo explícitamente autorizado funciona.
Implementación paso a paso
1. Modo Report-Only
Empieza sin bloquear, solo monitorizando:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /api/csp-report
Esto te permite ver qué se bloquearía sin romper nada.
2. Analizar los reportes
Los reportes CSP te dicen exactamente qué viola la política:
{
"csp-report": {
"document-uri": "https://tusitio.es/pagina",
"violated-directive": "script-src 'self'",
"blocked-uri": "https://cdn.externo.com/analytics.js",
"original-policy": "default-src 'self'"
}
}
3. Ajustar la política
Añade las fuentes legítimas que necesitas y mantén bloqueado el resto.
4. Activar en modo enforcement
Cambia Content-Security-Policy-Report-Only por Content-Security-Policy cuando estés satisfecho con la política.
CSP y servicios comunes
Google Analytics
script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com;
img-src 'self' https://www.google-analytics.com;
connect-src 'self' https://www.google-analytics.com https://analytics.google.com;
Google Fonts
style-src 'self' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
Alternativa más segura: descarga las fuentes y alójalas localmente.
YouTube embeds
frame-src https://www.youtube.com https://www.youtube-nocookie.com;
Stripe
script-src 'self' https://js.stripe.com;
frame-src https://js.stripe.com https://hooks.stripe.com;
connect-src 'self' https://api.stripe.com;
Errores frecuentes
Política demasiado permisiva. default-src * o script-src * anulan el propósito de CSP.
Olvidar object-src 'none'. Sin esta directiva, plugins como Flash (aunque obsoleto) podrían ejecutarse.
No monitorizar violaciones. Configura siempre un report-uri para detectar intentos de ataque y scripts rotos.
unsafe-inline en script-src. Destruye gran parte de la protección contra XSS. Usa nonces o hashes en su lugar.
CSP y cumplimiento normativo
Una Content Security Policy bien configurada contribuye al cumplimiento de varias regulaciones europeas. La directiva NIS2 exige medidas de seguridad proporcionales al riesgo, y CSP es una de las protecciones más efectivas contra inyección de código malicioso. El RGPD (artículo 32) requiere medidas técnicas adecuadas: una CSP reduce drásticamente el riesgo de exfiltración de datos personales mediante XSS. El Esquema Nacional de Seguridad (ENS) en España incluye la protección contra código malicioso como requisito, cubriendo directamente el ámbito de CSP.
Monitorización continua de CSP
Configurar CSP una vez no es suficiente. Cada nueva integración (analytics, chat widget, pasarela de pago) puede requerir ajustes en la política. Implementa un endpoint de reporting para recibir violaciones CSP en tiempo real:
Content-Security-Policy: [...]; report-uri /api/csp-report; report-to csp-endpoint
Revisa los reportes semanalmente para detectar tanto intentos de ataque (scripts bloqueados de orígenes desconocidos) como falsos positivos (recursos legítimos bloqueados). Herramientas como Report URI o Sentry pueden centralizar y analizar estos reportes automáticamente.
Escanea tu sitio web gratis con WarDek — OWASP, NIS2, RGPD, AI Act en un solo escaneo.