También disponible en: English · Português · Français · العربية
Generador y comprobador de CSP
Escribe una Content-Security-Policy y comprueba una URL real contra ella, viendo qué expresiones de tu política no hacen absolutamente nada.
¿Qué es una Content Security Policy?
Una Content Security Policy es una cabecera HTTP que le dice al navegador desde dónde puede cargar cosas una página. Es una lista de directivas (script-src, img-src, style-src y demás), cada una seguida de las fuentes que permite. Si la página intenta cargar algo que la política no permite, el navegador se niega.
La idea es limitar el daño. Si un atacante consigue inyectar marcado en tu página, una buena política es lo que impide que ese marcado cargue su script. La CSP no sustituye a escapar bien la salida; es la capa que limita lo grave que resulta el fallo cuando el escapado se tuerce.
Escribir una es fácil. Saber qué has escrito de verdad no lo es, y ese hueco es el que intenta cerrar esta página. Las reglas de coincidencia del CSP Level 3 son más sorprendentes de lo que parecen, y varias hacen que partes de una política se ignoren en silencio: una política puede listar una docena de hosts permitidos que no surten ningún efecto, y nada te avisa.
Cómo usarlo
- Empieza por una plantilla o pega tu propia política. La estricta se basa en nonce y es lo que recomiendan las guías actuales; la típica se parece más a lo que la mayoría de sitios lleva de verdad. Edita el texto libremente: todo lo de abajo se actualiza según escribes.
- Lee qué hace realmente la política. El panel de debajo enumera hallazgos: expresiones que se ignoran, directivas que faltan y fuentes que deshacen la protección que creías tener. Cada uno es una regla de la especificación, no una opinión.
- Y luego comprueba una URL real contra ella. Elige el tipo de recurso, pega la URL que quieres cargar y el origen desde el que se sirve tu página. Obtienes un veredicto, la directiva que se consultó tras la cadena de respaldo y la expresión exacta que lo decidió.
Las reglas de coincidencia que casi nadie conoce
La coincidencia de esquema es asimétrica y además hace upgrade. La especificación dice que el esquema http coincide con https, lo que significa que script-src http://example.com permite también https://example.com, pero no al revés. Escribir la forma insegura permite en silencio las dos. Esa misma regla hace que ws coincida con wss, http y https a la vez, una concesión bastante más amplia de lo que casi nadie pretende.
Un host comodín no incluye al propio dominio. El patrón *.example.com se resuelve quitando el asterisco inicial y exigiendo que el host termine en .example.com, y example.com no termina así. O sea que una política que permite *.example.com bloquea example.com, justo lo contrario de lo que casi todo el mundo cree haber escrito. También implica que ningún patrón de host coincide nunca con una dirección IP, porque el algoritmo exige un dominio.
Las rutas solo son coincidencia por prefijo cuando terminan en barra. Sin barra final la coincidencia es exacta, así que script-src https://cdn.example/js permite exactamente esa URL y nada por debajo. Además los segmentos se decodifican de porcentaje antes de comparar, con lo que una barra codificada sigue siendo un solo segmento y no dos.
Y los puertos caen al valor por defecto. Una fuente sin puerto coincide con el puerto por defecto del esquema, así que https://example.com y https://example.com:443 son el mismo origen, que es además lo que tiene que significar 'self'.
Las partes de tu política que no hacen nada
Hay dos reglas que hacen que ciertas expresiones estén en la política sin ningún efecto, y ninguna de las dos se ve si no sabes buscarla.
La primera es 'strict-dynamic'. Cuando aparece en script-src o default-src, la especificación dice que las fuentes de host y de esquema, junto con 'unsafe-inline' y 'self', se ignoran al cargar scripts. Solo siguen contando los nonce y los hash. Es deliberado y es cómo funciona el enfoque moderno basado en nonce, pero significa que una política que diga script-src 'strict-dynamic' 'nonce-abc' https://cdn.example 'self' no permite nada de ese CDN por su host. El comprobador enumera todas las expresiones que ha ignorado y dice qué regla las ignoró.
La segunda es 'unsafe-inline' junto a un nonce o un hash. En ese caso se ignora 'unsafe-inline', que es justamente el truco para escribir una política que degrade con elegancia en navegadores antiguos: los que entienden nonce obedecen al nonce y los que no recurren a 'unsafe-inline'. Útil cuando es deliberado y alarmante cuando es accidental, así que esta página distingue los dos casos en vez de marcar 'unsafe-inline' igual en ambos.
Hay un tercer hueco que es de ausencia y no de ignorar. Las directivas frame-ancestors, form-action y base-uri no recurren a default-src. Una política de default-src 'self' no restringe por tanto el enmarcado en absoluto, no restringe adónde se envían los formularios y deja base-uri abierto, de modo que el marcado inyectado puede reapuntar todas las URL relativas de la página. El comprobador te dirá claramente que no se aplica ninguna directiva.
Límites honestos
Esto comprueba la coincidencia de URL, que es la parte de la CSP con reglas de verdad y sorpresas de verdad. No modela todo lo que hace un navegador. El script y el estilo en línea, eval, las redirecciones, la herencia en workers, el sandbox, los trusted types y el envío de informes quedan fuera de lo que responde el comprobador, y una política que aquí permite una URL puede seguir bloqueando el recurso en un navegador por alguno de esos motivos.
Los nonce y los hash se reconocen pero no se evalúan. Que un script en línea concreto case con un nonce depende del marcado y no de la política, así que el comprobador los trata como expresiones que existen sin afirmar que dejen pasar ninguna URL en particular.
Los hallazgos son reglas, no una nota de seguridad. Una política puede pasar todas las comprobaciones de aquí y seguir siendo débil, porque la CSP no puede proteger a una página cuyo propio origen sirve script controlado por el atacante. Nada de esta página sustituye a codificar bien la salida.
No existe una batería de conformidad de CSP ni un comparador de referencia en npm que implemente los algoritmos de expresiones de fuente, así que el motor se comprobó contra los ejemplos trabajados de la propia especificación y sus algoritmos transcritos como aserciones con su número de sección. Cada regla asimétrica se prueba en las dos direcciones, porque una batería que solo comprueba la dirección permisiva la satisface una implementación que permite de más, que es justo el fallo que importa aquí.
¿Por qué es gratis?
Porque no cuesta nada mantenerlo. La política se analiza y la URL se comprueba en tu navegador según escribes; no se sube nada, no se registra nada y ningún servidor ve la política ni las URL que pegas.
Ni cuenta, ni registro, ni nada reservado. Las reglas de coincidencia salen de la especificación Content Security Policy Level 3 y no del resumen que hace otra web, y las comprobaciones que las verifican están guardadas junto a la página.