Por qué Content Security Policy es tu primera línea de defensa
CSP no es un firewall, es una whitelist de qué recursos puede cargar tu app. Sin CSP, cualquier script inyectado (XSS) se ejecuta con los permisos de tu dominio: acceso a cookies, localStorage, puede hacer requests a tu API. Con CSP, aunque un atacante inyecte <script>alert('hack')</script>, el navegador lo bloquea si no cumple la política. Es defensa en profundidad: asumís que tu código tiene bugs, pero limitás el daño. CSP también previene clickjacking con frame-ancestors, fuerza HTTPS con upgrade-insecure-requests, y bloquea plugins obsoletos con object-src 'none'. Una policy bien configurada reduce el riesgo de XSS en 90%.
Directivas CSP esenciales y qué controlan
default-src: Fallback para todo lo que no especifiques; empezá con 'self'. script-src: De dónde pueden venir scripts; evitá 'unsafe-inline' (permite XSS), usá nonces o hashes. style-src: Idem para CSS; librerías third-party suelen necesitar 'unsafe-inline'. img-src: Fuentes de imágenes; data: permite base64, https: permite cualquier HTTPS. connect-src: APIs y WebSockets permitidos; limitá a tus dominios. frame-ancestors: Quién puede embeber tu página; 'none' previene clickjacking. base-uri: Limita <base> tag (vector de ataque raro pero real). form-action: A dónde pueden submitear forms.
Migrar a CSP sin romper tu app en producción
Empezá con Content-Security-Policy-Report-Only: loggea violaciones sin bloquear nada. Configurá report-uri /csp-violations y analizá qué recursos se cargan (Google Fonts, CDNs, analytics). Agregá dominios a la whitelist gradualmente. Común encontrar: inline styles en componentes React, event handlers inline (onclick='...'), eval() en librerías viejas. Soluciones: extraer inline styles a archivos, usar event listeners programáticos, reemplazar librerías que usan eval. Una vez que Report-Only no muestra violaciones por 1 semana, activá el header real. Usá nonces dinámicos (genera un random por request) para scripts críticos que deben ser inline.
Errores comunes al configurar CSP
Usar 'unsafe-inline' y 'unsafe-eval' por default: Anula 80% de la protección CSP; solo usá si no hay alternativa y entendés el riesgo. Olvidar 'self' en default-src: Si ponés default-src https:, tus propios scripts fallan; siempre incluí 'self'. No especificar protocol en dominios: cdn.example.com permite HTTP y HTTPS; mejor https://cdn.example.com. Whitelist demasiado amplia: script-src https: permite cualquier HTTPS, incluyendo CDNs comprometidos; sé específico. No testear en todos los navegadores: Safari tiene quirks con CSP; probá antes de producción. No versionar policies: Guardá tu CSP en git; sabés qué cambió si algo rompe.