Introducción
El navegador debe aplicar el CSP siempre y cuando permanezca en la página, y no solo mientras se carga o renderiza originalmente. Todo lo demás lo haría bastante desdentado.
Por lo tanto, el comportamiento que está experimentando no tiene nada que ver con cuando se carga el script. En cambio, se trata de lo que lo carga. Hay dos problemas.
Problema 1: estricto-dinámico
Dejaré que Mozilla lo explique:
La directiva de dinámica estricta especifica que la confianza dada explícitamente a un script presente en el marcado, acompañándolo con un nonce o un hash, se propagará a todos los scripts cargados por ese script raíz.
Por lo tanto, cuando confía en un script dándole un nonce, puede a su vez cargar otros scripts. Eso significa que si tiene una vulnerabilidad DOM XSS en un script con un nonce, el CSP no lo salvará. La solución es eliminar 'strict-dynamic'
(pero eso, por supuesto, será problemático si confía en esta función).
Problema 2: unsafe-eval
Para cargar el script, usa jQuery .html()
. En algún lugar del código fuente de jQuery (línea 343 para ser exactos) hace una llamada a los viejos. eval()
.
Así que si ejecuta el código
$(".test").html("<scr" + "ipt>alert('XSS');</scr" + "ipt>");
jQuery por alguna razón (no me preguntes por qué, he intentado y no he seguido el código fuente) ejecutará lo siguiente:
eval("alert('XSS');");
Esto significa que el CSP ya no se aplica: después de todo, no estás creando una nueva etiqueta de script, estás evaluando una cadena.
Aquí la solución es eliminar 'unsafe-eval'
del CSP, pero eso rompería jQuery. La solución a eso podría ser actualizar a jQuery 3, que al inspeccionar superficialmente la fuente parece haber solucionado esto.
Conclusión
Esto significa que todo el código (usando jQuery 2) en el formulario
x.html(unsafeFromURL);
puede ser vulnerable a XSS incluso si se establece un CSP . Creo que esto es inesperado para mucha gente (fue para mí). Pero sirve como un recordatorio de otro punto importante: No debes usar CSP como tu única línea de defensa contra XSS .
También tenga en cuenta que esto no es un problema con el funcionamiento de CSP, sino con el funcionamiento de jQuery.