Introduzione
CSP dovrebbe essere applicato dal browser fino a quando rimani sulla pagina, e non solo mentre è caricato o reso in origine. Tutto il resto lo renderebbe abbastanza sdolcinato.
Quindi il comportamento che stai riscontrando non ha nulla a che fare con quando lo script è caricato. Invece si tratta di cosa lo carica. Ci sono due problemi.
Problema 1: rigoroso-dinamico
Lascio che Mozilla lo spieghi:
The strict-dynamic directive specifies that the trust explicitly given to a script present in the markup, by accompanying it with a nonce or a hash, shall be propagated to all the scripts loaded by that root script.
Quindi, quando ti fidi di uno script dandogli un nonce, può a sua volta caricare altri script. Ciò significa che se hai una vulnerabilità DOM XSS in uno script con un nonce, il CSP non ti salverà. La soluzione è rimuovere 'strict-dynamic'
(ma ciò sarà certamente problematico se ti affidi a questa funzione).
Problema 2: non sicuro-eval
Per caricare lo script, usi jQuery .html()
. Da qualche parte nel codice sorgente jQuery (riga 343 per l'esattezza) fa una chiamata al buon vecchio eval()
.
Quindi se esegui il codice
$(".test").html("<scr" + "ipt>alert('XSS');</scr" + "ipt>");
jQuery per qualche motivo (non chiedermi perché, ho provato e non sono riuscito a seguire il codice sorgente) esegui quanto segue:
eval("alert('XSS');");
Questo significa che il CSP non si applica più: dopo tutto non stai creando un nuovo tag script, stai valutando una stringa.
Qui la soluzione è rimuovere 'unsafe-eval'
dal CSP, ma ciò interromperà jQuery. La soluzione potrebbe essere l'aggiornamento a jQuery 3, che su un'ispezione superficiale della sorgente sembra aver risolto questo problema.
Conclusione
Ciò significa che tutto il codice (utilizzando jQuery 2) nel modulo
x.html(unsafeFromURL);
può essere vulnerabile a XSS anche se è stato impostato un CSP . Penso che questo sia inaspettato per molte persone (era per me). Ma serve come promemoria di un altro punto importante: Non dovresti usare CSP come unica linea di difesa contro XSS .
Nota anche che questo non è un problema con il funzionamento di CSP, ma con il funzionamento di jQuery.