La cabecera mas poderosa que casi nadie configura bien
Content-Security-Policy (CSP) es, sin discusion, la cabecera de seguridad HTTP mas potente que existe. Funciona como una lista blanca que indica al navegador exactamente que recursos tienen permiso para cargarse y ejecutarse en tu pagina: scripts, estilos, imagenes, fuentes, iframes y conexiones de red.
Bien configurada, CSP neutraliza la gran mayoria de ataques Cross-Site Scripting (XSS). Mal configurada, o directamente ausente, tu sitio queda expuesto a una de las vulnerabilidades mas explotadas de la web. Segun multiples estudios de seguridad, mas del 90% de los sitios web no tienen CSP o la implementan con errores que anulan su proteccion.
XSS: el ataque que CSP previene
Cross-Site Scripting (XSS) es un tipo de ataque en el que un atacante consigue inyectar codigo JavaScript malicioso en tu pagina web. El mecanismo es simple pero devastador:
- El atacante inyecta una etiqueta
<script>o un manejador de eventos inline (onclick,onerror) en tu pagina, ya sea a traves de un campo de formulario, un parametro de URL o un contenido almacenado en base de datos. - El navegador del usuario no distingue los scripts legitimos de los inyectados: los ejecuta todos por igual.
- El script malicioso puede robar cookies de sesion, redirigir al usuario a sitios de phishing, capturar pulsaciones de teclado o modificar el contenido visible de la pagina.
Existen tres variantes principales: XSS reflejado (el payload viaja en la URL), XSS almacenado (el payload se guarda en el servidor y se sirve a todos los visitantes) y XSS basado en DOM (el payload se ejecuta manipulando el DOM del lado del cliente). CSP mitiga las tres variantes.
La solucion que aporta CSP es conceptualmente elegante: le dice al navegador "solo ejecuta scripts que provengan de estos origenes especificos". Si un atacante inyecta un <script> apuntando a un dominio no autorizado, el navegador lo bloquea antes de ejecutarlo.
Las directivas CSP explicadas
CSP se compone de directivas, cada una controlando un tipo de recurso. Estas son las esenciales:
default-src-- La directiva de respaldo. Si no defines una directiva especifica para un tipo de recurso, se aplica esta. Es la base de cualquier politica solida.script-src-- Define desde donde pueden cargarse los scripts. Es la directiva mas critica porque controla la ejecucion de JavaScript.style-src-- Controla el origen de las hojas de estilo CSS.img-src-- Define desde donde pueden cargarse las imagenes.connect-src-- Restringe los destinos defetch(),XMLHttpRequest, WebSocket y EventSource.font-src-- Controla desde donde pueden cargarse las fuentes tipograficas.frame-src/frame-ancestors--frame-srccontrola que origenes puede tu pagina cargar en iframes.frame-ancestorscontrola que paginas pueden cargar la tuya en un iframe (reemplaza a X-Frame-Options).report-uri/report-to-- Define a donde se envian los informes de violaciones de la politica. Esencial para monitorizar y depurar.upgrade-insecure-requests-- Instruye al navegador para que convierta automaticamente todas las peticiones HTTP a HTTPS.
Los 5 errores mas comunes en CSP
Error 1: unsafe-inline en script-src
Content-Security-Policy: script-src 'self' 'unsafe-inline'
Esta unica directiva anula la mayor parte de la proteccion de CSP contra XSS. Si permites scripts inline, un atacante que inyecte <script>alert(document.cookie)</script> tendra exito. Si necesitas scripts inline, usa nonces o hashes en su lugar:
Content-Security-Policy: script-src 'self' 'nonce-a8F3kL9mPq'
Solo se ejecutaran los scripts con el atributo nonce="a8F3kL9mPq", un valor que cambia en cada respuesta del servidor y que el atacante no puede predecir.
Error 2: unsafe-eval
Content-Security-Policy: script-src 'self' 'unsafe-eval'
Permite eval(), new Function(), setTimeout('string') y otras formas de ejecucion dinamica de codigo. Muchos desarrolladores lo anaden para que ciertos frameworks o librerias dejen de dar errores, pero abre un agujero de seguridad enorme. Siempre existe una alternativa mas segura.
Error 3: Fuentes con comodin
Content-Security-Policy: script-src *
Un comodin en script-src es practicamente equivalente a no tener CSP. Un atacante puede alojar un script malicioso en cualquier dominio del mundo y tu navegador lo ejecutara. Lo mismo aplica a patrones excesivamente amplios como *.example.com: cualquier subdominio comprometido se convierte en vector de ataque.
Error 4: Ausencia de default-src
Sin una directiva default-src, cualquier tipo de recurso que no tenga su propia directiva explicita queda sin restriccion alguna. Esto significa que un atacante podria explotar tipos de recursos que olvidaste cubrir (por ejemplo, WebSockets mediante connect-src o fuentes mediante font-src).
Error 5: Report-Only para siempre
Content-Security-Policy-Report-Only: default-src 'self'
Report-Only es excelente para la fase de pruebas: registra las violaciones sin bloquearlas. El problema es que muchos sitios lo despliegan y nunca pasan al modo de aplicacion real. Meses o anos despues, la cabecera sigue en modo "solo informar" y no proporciona ninguna proteccion efectiva.
Construir una CSP desde cero
El enfoque correcto es iterativo. Estos son los pasos:
Paso 1: Desplegar en modo Report-Only
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
Paso 2: Monitorizar los informes durante 1-2 semanas. Identifica que recursos legitimos estan siendo flagueados como violaciones.
Paso 3: Anadir fuentes legitimas una a una. Si usas Google Analytics, anade https://www.google-analytics.com a script-src. Si cargas fuentes de Google Fonts, anade https://fonts.googleapis.com a style-src y https://fonts.gstatic.com a font-src.
Paso 4: Reemplazar unsafe-inline con nonces. Genera un nonce criptografico unico por respuesta e incluyeló en cada <script> y en la directiva CSP.
Paso 5: Pasar a modo de aplicacion. Cambia Content-Security-Policy-Report-Only por Content-Security-Policy.
Paso 6: Seguir monitorizando. Mantener report-uri activo incluso en modo enforcement para detectar regresiones.
CSP mala vs. CSP buena
Mala (proteccion nula):
Content-Security-Policy: default-src *; script-src * 'unsafe-inline' 'unsafe-eval'
Buena (proteccion solida):
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-rAnd0mV4lue'; style-src 'self' 'nonce-rAnd0mV4lue'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https://api.example.com; frame-ancestors 'none'; upgrade-insecure-requests; report-uri /csp-report
Funcionalidades de CSP Level 3
La version mas reciente de la especificacion introduce mejoras significativas:
strict-dynamic-- Permite que los scripts ya autorizados (via nonce o hash) carguen scripts adicionales sin necesidad de listar cada dominio. Simplifica enormemente el mantenimiento de la politica.- Enfoque basado en nonces -- Recomendado por Google como la forma mas robusta de implementar CSP. Un nonce unico por respuesta reemplaza la necesidad de listar origenes.
trusted-types-- Previene XSS basado en DOM forzando que todos los valores asignados a "sinks" peligrosos (comoinnerHTML) pasen por funciones de sanitizacion previamente registradas.
Que evalua UareSafe
UareSafe analiza automaticamente la cabecera Content-Security-Policy de tu sitio como parte de la dimension de Seguridad Tecnica. Concretamente verifica:
- Presencia de la cabecera CSP (no solo Report-Only)
- Ausencia de
unsafe-inlineyunsafe-evalenscript-src - Existencia de una directiva
default-src - Deteccion de comodines excesivamente permisivos
- Modo Report-Only sin enforcement activo
Estos controles forman parte de los 8 controles de cabeceras de seguridad que UareSafe evalua dentro de la dimension de Seguridad Tecnica (30% de la puntuacion total de certificacion).
Conclusion
CSP no es opcional en 2026. Es la defensa mas eficaz contra Cross-Site Scripting, el ataque web mas prevalente de las ultimas dos decadas. Una politica CSP correctamente configurada protege a tus usuarios de scripts maliciosos, filtraciones de datos y secuestros de sesion.
El proceso es claro: empieza en modo Report-Only, monitoriza, itera y pasa a enforcement. No necesitas una politica perfecta desde el primer dia, pero si necesitas empezar. Tus usuarios merecen una experiencia de navegacion segura, y tu sitio merece una proteccion que este a la altura de las amenazas actuales.