La CSP è un header HTTP, non un plugin. Dice al browser da dove può caricare gli script. Report-Only prima, enforcement dopo. unsafe-inline la svuota. Un overlay anti-XSS è un altro script.
Un plugin «anti-XSS» che inietta uno script in pagina non è una Content Security Policy. È un altro script. La CSP è un header HTTP: dice al browser da dove può caricare script, stili, immagini, e se può eseguire il JavaScript scritto in chiaro nel HTML. Senza quell’header, il browser esegue ciò che trova. Con unsafe-inline dappertutto, l’header c’è e non fa il mestiere.
In breve: la Content-Security-Policy si spedisce dal server, su tutte le risposte, non solo sulla home. Serve come seconda linea contro XSS e clickjacking, non al posto della sanificazione dell’output. OWASP distingue policy strict (nonce o hash) e policy a allowlist. Report-Only si usa per misurare, poi si passa all’enforcement. Un CMS pieno di plugin inline spesso non sopravvive a una policy strict: è un dato di fatto, non un motivo per non partire.
Cosa trovi in questo articolo
Cosa fa una CSP, e cosa non è
OWASP, nella Content Security Policy Cheat Sheet, la inquadra come difesa in profondità lato client. Il server inietta l’header; il browser rifiuta chiamate che caricherebbero contenuto non previsto. Non elimina le vulnerabilità. Le rende più difficili da sfruttare.
Cinque mestieri, sempre da quella scheda:
| Direttiva / effetto | Cosa blocca, se è scritta bene | Cosa non blocca da sola |
|---|---|---|
| Niente script inline | Un tag script iniettato nella pagina | Un XSS che passa da un file JS già autorizzato |
| Niente script da origini arbitrarie | Uno script caricato da un host non in elenco | Un CDN compromesso se quel CDN è in allowlist |
| Niente compilazione di testo in JavaScript a runtime | Testo trasformato in codice eseguibile dal browser | Logica insicura già nel bundle |
form-action | Un form di phishing iniettato che posta altrove | Un form legittimo mal protetto lato server |
frame-ancestors | Clickjacking e parte degli xs-leaks da iframe | Sostituisce X-Frame-Options; non sostituisce CSRF |
OWASP è esplicita: anche su un sito statico, senza input utente, una CSP può imporre Subresource Integrity sugli script di terzi. Se il fornitore di analytics viene compromesso, il browser non esegue il file alterato, a patto che l’hash non torni. Resta una seconda linea. La prima è ancora la prevenzione XSS descritta nell’altra cheat sheet OWASP. Un WAF, per confronto, filtra richieste: è un altro strato, trattato in WAF: cosa blocca e cosa non può risolvere. La CSP non è un WAF. Non è un overlay. Non è un certificato: il transito sta nella checklist TLS.
Questo pezzo sta nel cluster Sicurezza.
Tre modi di consegnarla: uno solo è completo
OWASP elenca tre veicoli. MDN, nella guida Content Security Policy, coincide sul preferito.
| Veicolo | Enforcement | Limite |
|---|---|---|
Content-Security-Policy (header di risposta) | Sì | Nessuno rilevante: è il modo standard. Va su tutte le risposte, non solo l’index |
Content-Security-Policy-Report-Only | No: solo report in console e all’endpoint | Serve a misurare prima di rompere il sito. Non protegge |
| Elemento meta http-equiv Content-Security-Policy | Parziale | OWASP avverte: non supporta l’insieme completo delle direttive (in particolare reporting e alcune di navigazione). Non è il canale da produzione |
Report-Only e Policy si possono spedire insieme: si misura la nuova, si tiene in vita la vecchia. L’endpoint di report (report-uri / report-to) è parte del lavoro, non un extra. Senza report si naviga alla cieca, e il primo giorno di enforcement è il giorno in cui il checkout smette di parlare con il PSP.
Strict vs allowlist: la scelta che conta
OWASP divide le policy in due famiglie.
Strict CSP. Gli script inline autorizzati portano un nonce (valore casuale per risposta) o un hash del contenuto. strict-dynamic consente a uno script già fidato di caricarne altri, senza tenere una lista di host. È il modello che resiste meglio a un XSS classico: l’attaccante non conosce il nonce della risposta. Il nonce va generato per ogni documento. Riutilizzarlo, o metterlo in cache con la pagina, lo brucia.
Allowlist (granulare). Si elencano origini: script-src 'self' https://cdn.example. È più facile da spiegare in una riunione. È più fragile: ogni host in lista è una porta. Un JSONP su quel CDN, o un file che l’attaccante riesce a far ospitare lì, passa. OWASP la considera accettabile in transizione, non come obiettivo.
Una policy «base» non-strict, nella stessa cheat sheet, usa 'self', blocca object-src, imposta frame-ancestors 'none' o il proprio origine, e può aggiungere upgrade-insecure-requests. Quest’ultima chiede al browser di promuovere HTTP in HTTPS: è un complemento al redirect lato server, non un sostituto. Il lucchetto, da solo, non è una CSP.
Cosa si rompe su un CMS a plugin
Il costo vero di una CSP non è l’header. È l’inventario di ciò che la pagina già esegue. Su un CMS a plugin il conto è questo, e non è una stima di traffico: è ciò che si vede in Report-Only in una settimana.
| Sintomo in report | Cosa sta succedendo | Cosa non fare |
|---|---|---|
Blocco di script-src su inline | Un modulo scrive JavaScript inline in pagina: analytics, chat, pixel, overlay | Aggiungere 'unsafe-inline' e dichiarare il lavoro finito |
| Blocco su un host sconosciuto | Un plugin carica JS da un dominio che non era nel preventivo | Allargare l’allowlist «così non si rompe». Si misura, si decide, o si toglie il plugin |
| Blocco della compilazione a runtime | Una libreria vecchia compila template in JavaScript a runtime | Riattivare quella compilazione per sempre. Si aggiorna la libreria o si isola |
| Checkout o area admin muti | form-action o connect-src non includono PSP, API, WebSocket | Spegnere la CSP. Si aggiunge l’origine giusta, non * |
| Frame del sito su un partner | frame-ancestors 'none' è corretto per il sito pubblico, sbagliato se un partner deve embeddare | Copiare *. Si elenca l’origine del partner |
Il contributo, qui, non è una policy da copiare. È l’ordine: Report-Only su staging, una settimana di report, inventario, nonce dove il tema lo consente, enforcement a pezzi (default-src stretto, script dopo). Un overlay che promette «conformità» aggiungendo un file JS è il contrario di una CSP: allarga la superficie. Il costo nascosto di quei moduli sta in il costo nascosto dei plugin; le patch, in ritmo delle patch. La CSP non li sostituisce.
Errori da evitare
Spedire
'unsafe-inline'suscript-srce chiamarla una CSP.Mettere la policy solo in un meta http-equiv e credere di avere reporting e direttive complete.
Enforcement in produzione il primo giorno, senza Report-Only.
Un nonce messo in cache con l’HTML. Non è più un nonce.
Confondere CSP e WAF, o CSP e certificato TLS.
Comprare un overlay XSS e togliere l’header «perché adesso c’è il plugin».
In sintesi
La Content-Security-Policy è un header, su tutte le risposte. Dice al browser cosa può eseguire. OWASP la vuole strict, con nonce o hash, e Report-Only prima dell’enforcement. unsafe-inline la svuota. Un plugin che inietta script è un problema da inventariare, non una soluzione. XSS si previene nel codice; la CSP è la seconda linea, se la si scrive.
Fonti
OWASP, Content Security Policy Cheat Sheet (consultata il 15 settembre 2026).
OWASP, Cross-Site Scripting Prevention Cheat Sheet (la CSP non la sostituisce).
Immagine di copertina: tastiera e schermo. La Content-Security-Policy si pubblica nell’header HTTP, non in un plugin. Foto di Thomas Lefebvre, Unsplash via Wikimedia Commons, licenza CC0.
Questo contenuto è stato realizzato con il supporto di sistemi di intelligenza artificiale e successivamente verificato secondo le linee editoriali della redazione.