Generador de CSP
Danos la dirección de una página real. Leemos su HTML, enumeramos todos los lugares desde los que carga scripts, estilos, imágenes, fuentes y marcos, y escribimos una política que puedes probar en modo solo informe, donde no puede romper nada.
Una lista de invitados para tus propias páginas
Un navegador hace lo que le diga una página. Si el HTML dice “ejecuta este script de aquel servidor”, se ejecuta. Eso se vuelve peligroso el día en que otra persona consigue añadir una línea a tu página, por un campo de comentarios que nadie limpió, un plugin comprometido o un anuncio. El navegador no tiene forma de distinguir su línea de la tuya.
Una Content-Security-Policy (CSP) es un encabezado de respuesta con el que le dices al navegador, por adelantado, desde dónde puede cargar cosas esta página. Se lee como una lista de invitados, con una línea por tipo de recurso:
default-src 'self';
script-src 'self' https://cdn.example.com;
img-src 'self' data: https://images.example.net;
object-src 'none'Cada línea es una directiva. 'self' significa el origen de la propia página. Todo lo que no está en la lista se rechaza, y el rechazo queda registrado en la consola del navegador.
Cómo construye esta página el borrador
Nuestro servidor descarga la dirección una vez y analiza el HTML como lo haría un navegador, sin ejecutar nada. Cada dirección que encuentra se reduce a su origen (esquema y host, sin ruta) y se archiva:
| Directiva | Se lee de |
|---|---|
script-src | <script src>, precargas de módulos y direcciones de scripts nombradas dentro de fragmentos de carga en línea |
style-src | enlaces a hojas de estilo y reglas @import |
img-src, font-src | etiquetas de imagen, srcset, iconos, pósteres, precargas y url() en CSS en línea y en las primeras cuatro hojas de estilo del propio origen del sitio |
frame-src, media-src, object-src, manifest-src | marcos, audio y vídeo, plugins, el enlace al manifiesto |
form-action, base-uri | destinos de formularios y la etiqueta <base> |
connect-src | solo las sugerencias de preconexión y los endpoints documentados de algunos servicios que se encuentran en la página (Google Analytics, Google Fonts, Cloudflare Web Analytics) |
El borrador parte de default-src 'self', añade una línea por directiva y cierra las puertas que no tienen alternativa: object-src 'none', base-uri 'self', frame-ancestors 'self', además de upgrade-insecure-requests en las páginas HTTPS. Si la página ya envía una política, en un encabezado o en una etiqueta meta, te la mostramos y la comparamos con lo que carga la página.
La parte difícil: el código en línea
El código inyectado es casi siempre en línea, como un bloque <script> o un atributo onclick escrito en la página. Una política que valga la pena prohíbe, entonces, el código en línea. El problema es que la mayoría de los sitios tienen mucho propio. La herramienta cuenta los bloques de script, los atributos de manejadores de eventos, los enlaces javascript:, los bloques de estilo y los atributos style=, y luego te da dos borradores.
- El borrador estricto no tiene
'unsafe-inline'. Es donde quieres acabar, y rompería el código en línea contado arriba. - El borrador de transición añade
'unsafe-inline'donde la página lo necesita. Sigue limitando desde qué sitios se puede cargar contenido, pero ya no frena los scripts en línea inyectados, por eso se marca como débil.
Hay tres maneras de pasar de uno a otro. Mover el código a archivos, hacer que el servidor marque cada etiqueta con un nonce distinto en cada respuesta, o enumerar en la política el hash SHA-256 de cada bloque. La herramienta calcula esos hashes para los bloques de script que encontró. Solo sirven para bloques cuyo texto nunca cambia.
Primero en modo solo informe, siempre
Envía el borrador como Content-Security-Policy-Report-Only. El navegador no hace cumplir nada y registra lo que habría bloqueado. Recorre el sitio con la consola abierta, añade lo que falte de forma legítima y repite hasta que el registro se quede en silencio. Entonces cambia el nombre del encabezado a Content-Security-Policy. Obtienes fragmentos para Apache, nginx y una etiqueta meta. La forma con meta no admite el modo solo informe ni frame-ancestors.
El borrador sale de una sola página, leída una vez, sin ejecutar nada. No puede ver las solicitudes que hacen los scripts después de cargar (balizas de analítica, widgets de chat, marcos de pago, imágenes de carga diferida), lo que reciben los visitantes con sesión iniciada ni ninguna otra página del sitio. Cuenta con tener que añadir fuentes. Para una calificación de los encabezados que envía hoy una página, usa la calificación de encabezados de seguridad.
Preguntas frecuentes
¿Una Content-Security-Policy romperá mi sitio?
Una política aplicada bloquea todo lo que no enumera, así que una equivocada sí lo hará. Una política en modo solo informe no puede romper nada, porque lo único que hace es registrar. Empieza por ahí y pasa a aplicarla cuando la consola no muestre ninguna infracción en tus páginas principales.
¿Vale la pena una política con unsafe-inline?
En parte. Sigue restringiendo adónde pueden ir los scripts, los marcos y los envíos de formularios, bloquea los plugins y evita el secuestro de la etiqueta <base>. No detiene a un atacante que pueda escribir un bloque de script en la página, y esa es la razón principal para tener una política. Úsala como un paso del camino.
¿Cuál es la diferencia entre un nonce y un hash?
Un nonce es un valor aleatorio que el servidor genera para cada respuesta y repite en cada etiqueta de script de confianza. Un hash es la huella de un bloque de código concreto, indicada en la política. Los nonces van bien en páginas que se construyen en cada solicitud. Los hashes van bien para unos pocos fragmentos estáticos en páginas que pueden guardarse en caché.
¿Por qué se omiten las rutas en la política generada?
CSP admite rutas como https://cdn.example.com/lib/, pero se ignoran tras una redirección y se rompen en cuanto se mueve un archivo. La mayoría de las políticas en producción enumeran orígenes. Si un origen aloja archivos de muchas partes, como un CDN público, fija además los archivos exactos con hashes de integridad.
¿Puedo definir una CSP en WordPress u otro CMS?
Sí, mediante la configuración del servidor web o un plugin de seguridad que envíe encabezados. El tema y los plugins traerán una larga lista de scripts y estilos en línea, así que empieza con el encabezado de solo informe y el borrador de transición, y reduce después el código en línea plugin por plugin.
¿Dónde veo lo que bloquea la política?
En la pestaña Consola de las herramientas para desarrolladores del navegador. Cada infracción nombra la directiva y la dirección bloqueada. Para recogerlas de los visitantes, añade una directiva report-uri o report-to que apunte a un colector.