Command Palette

Search for a command to run...

Content Security Policy (CSP): Configuración y Mejores Prácticas

Aprende qué es Content Security Policy, cómo configurar directivas CSP para prevenir XSS y controlar qué recursos puede cargar tu aplicación.

Lectura: 16 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • Content-Security-Policy header define listas blancas con directivas como script-src 'self', style-src 'nonce-abc123'
  • Bloquea scripts inline y eval() a menos que uses nonces (nonce-xyz) o hashes SHA256
  • default-src 'none' bloquea todo por defecto, luego especificas qué permitir en cada directiva
  • securitypolicyviolation event detecta violaciones en el navegador con blockedURI y violatedDirective
  • Content-Security-Policy-Report-Only reporta violaciones sin bloquear recursos (ideal para testing)

Introducción a CSP

Content Security Policy (CSP) es un estándar de seguridad que permite a los administradores de sitios web declarar fuentes de contenido aprobadas que los navegadores pueden cargar para esa página. Con CSP, puedes controlar qué scripts, estilos, imágenes, fuentes y otros recursos pueden ejecutarse o cargarse, reduciendo significativamente el riesgo de ataques XSS y otras vulnerabilidades de inyección.

CSP funciona como una lista blanca de recursos permitidos. Cuando un navegador encuentra un recurso (script, estilo, imagen, etc.), verifica si cumple con las directivas CSP. Si el recurso no está en la lista blanca, el navegador lo bloquea y reporta una violación. Esto previene que scripts maliciosos se ejecuten, incluso si logran inyectarse en la página.

CSP vs XSS

Mientras que XSS previene la inyección de scripts mediante validación y escaping, CSP bloquea la ejecución de scripts que no estén explícitamente permitidos. CSP es una capa adicional de defensa que complementa pero no reemplaza las prácticas de prevención de XSS.

Cómo Funciona CSP

CSP funciona mediante directivas que especifican qué fuentes de contenido son permitidas para diferentes tipos de recursos. Cada directiva controla un tipo específico de recurso, y puedes configurar múltiples directivas en una sola política CSP.

  • <strong>Header HTTP</strong>: El servidor envía el header Content-Security-Policy con las directivas
  • <strong>Meta tag</strong>: Alternativa para configurar CSP desde el HTML (menos seguro)
  • <strong>Evaluación</strong>: El navegador evalúa cada recurso contra las directivas CSP
  • <strong>Bloqueo</strong>: Los recursos no permitidos se bloquean antes de cargarse
  • <strong>Reporte</strong>: Las violaciones se reportan a una URL configurada

Directivas CSP

Las directivas CSP definen qué fuentes de contenido son permitidas para diferentes tipos de recursos. Entender estas directivas es fundamental para configurar una política CSP efectiva.

directivas-csp.js
Loading code...

default-src 'self' establece que por defecto solo se permiten recursos del mismo origen. script-src 'self' 'nonce-abc123' permite scripts del mismo origen y scripts inline con el nonce específico. img-src 'self' data: https: permite imágenes del mismo origen, data URIs y cualquier origen HTTPS. object-src 'none' bloquea completamente plugins como Flash. frame-ancestors 'none' previene que tu sitio sea embebido en iframes (protección contra clickjacking).

Directiva default-src

default-src es la directiva más importante porque define la política por defecto para todos los recursos. Si configuras default-src como 'none', todos los recursos estarán bloqueados a menos que especifiques directivas específicas para cada tipo de recurso.

Implementación de CSP

La implementación de CSP puede hacerse de dos formas: mediante headers HTTP (recomendado) o mediante meta tags en el HTML. Los headers HTTP son más seguros porque no pueden ser modificados por scripts del cliente.

  • <strong>Headers HTTP</strong>: Configuración en el servidor (más seguro)
  • <strong>Meta tags</strong>: Configuración en el HTML (menos seguro)
  • <strong>Report-only mode</strong>: Prueba la política sin bloquear recursos
  • <strong>Reporte de violaciones</strong>: Recibe alertas de recursos bloqueados
  • <strong>Nonce y hash</strong>: Permite scripts específicos con tokens o hashes

CSP en Headers HTTP

Configurar CSP en headers HTTP es la forma más segura de implementar Content Security Policy. Los headers se envían desde el servidor y no pueden ser modificados por scripts del cliente.

csp-headers.js
Loading code...

El middleware Express usa res.setHeader('Content-Security-Policy', csp) para enviar el header en cada respuesta. Los nonces deben generarse dinámicamente con crypto.getRandomValues() en cada request y pasarse al template HTML como <script nonce="{{nonce}}">. Content-Security-Policy-Report-Only permite probar la política sin bloquear recursos, solo reportando violaciones a report-uri /csp-violations.

Report-Only Mode

Usa Content-Security-Policy-Report-Only para probar tu política CSP sin bloquear recursos. El navegador reportará violaciones pero permitirá que los recursos se carguen. Esto es esencial para depurar y ajustar tu política antes de aplicarla en producción.

CSP en Meta Tag

Los meta tags permiten configurar CSP directamente en el HTML. Aunque es menos seguro que los headers HTTP, puede ser útil en situaciones donde no tienes control sobre la configuración del servidor.

csp-meta.js
Loading code...

El meta tag <meta http-equiv="Content-Security-Policy" content="..."> define la política CSP directamente en el HTML. Los scripts con nonce="abc123" son permitidos mientras que scripts sin nonce son bloqueados. Sin embargo, scripts maliciosos pueden remover el meta tag antes de ejecutarse, y no soporta directivas importantes como report-uri y frame-ancestors. Úsalo solo cuando no tienes acceso al servidor.

Limitaciones de Meta Tags

Los meta tags CSP tienen limitaciones importantes: no pueden usar report-uri, no pueden bloquear frame-ancestors, y scripts maliciosos pueden modificarlos. Siempre que sea posible, usa headers HTTP en lugar de meta tags.

Reporte de Violaciones

El reporte de violaciones te permite recibir alertas cuando la política CSP bloquea recursos. Esto es esencial para depurar y ajustar tu política CSP, y para detectar intentos de ataques.

reporte-violaciones-csp.js
Loading code...

El evento securitypolicyviolation se dispara en el navegador cada vez que CSP bloquea un recurso. evento.blockedURI contiene la URL del recurso bloqueado, evento.violatedDirective indica qué directiva se violó (ej: "script-src"), y evento.sourceFile + evento.lineNumber identifican dónde ocurrió. Puedes enviar estos datos a tu servidor con fetch('/csp-violations') para almacenarlos y analizar patrones de ataques.

Procesamiento de Reportes

Los reportes de violaciones deben procesarse en el servidor. Puedes almacenarlos en una base de datos para análisis, enviar alertas a tu equipo de seguridad, o usar servicios de terceros como Report URI. Analiza los reportes regularmente para identificar patrones de ataques.

Errores Comunes

Estos son los errores más frecuentes al configurar CSP y cómo evitarlos.

errores-comunes-csp.js
Loading code...

script-src 'unsafe-inline' 'unsafe-eval' permite scripts inline y eval(), anulando completamente la protección contra XSS. script-src * permite scripts de cualquier origen (demasiado permisivo). default-src 'none' sin otras directivas bloquea TODO (scripts, estilos, imágenes). No configurar report-uri significa que no sabrás qué violaciones ocurren. Siempre usa Content-Security-Policy-Report-Only primero para probar sin romper tu aplicación.

Evitar unsafe-inline y unsafe-eval

Las directivas 'unsafe-inline' y 'unsafe-eval' permiten scripts inline y la función eval(), lo que anula la protección de CSP contra XSS. En su lugar, usa nonces o hashes para permitir scripts específicos de forma segura.

Resumen: Content Security Policy

Conceptos principales:

  • script-src 'self' 'nonce-abc123' permite scripts del mismo origen y con nonce específico
  • default-src 'none' bloquea todo por defecto, luego especificas script-src, style-src, img-src
  • object-src 'none' bloquea plugins, frame-ancestors 'none' previene clickjacking
  • res.setHeader('Content-Security-Policy', csp) en Express envía el header HTTP
  • securitypolicyviolation event expone blockedURI, violatedDirective, sourceFile, lineNumber

Mejores prácticas:

  • Content-Security-Policy-Report-Only para probar sin bloquear recursos
  • Genera nonces dinámicos con crypto.getRandomValues() por cada request
  • Evita 'unsafe-inline' y 'unsafe-eval' - usan nonces como script-src 'nonce-xyz'
  • Configura report-uri /csp-violations para recibir reportes JSON de violaciones
  • Usa headers HTTP, no meta tags (headers no pueden ser modificados por scripts)