# Componi una CSP a prova di XSS, o valida quella che già usi

> Builder e validatore di Content-Security-Policy: componi l'header CSP anti-XSS scegliendo le direttive, o analizza una policy esistente. Client-side, gratis.

Strumento gratuito nel browser (nessun upload): https://www.mauriziofonte.it/strumenti/generatore-csp-content-security-policy

Due strumenti in uno. Il **builder** compone un header **Content-Security-Policy** scegliendo le direttive principali (`default-src`, `script-src`, `frame-ancestors` e altre) con valori canonici come `'self'`, `'none'`, nonce e `'strict-dynamic'`. Il **validatore** analizza una CSP che incolli e ti segnala le debolezze che vanificano la protezione: `'unsafe-inline'`, wildcard `*`, `data:` in `script-src`, assenza di `default-src` o `frame-ancestors`. Tutto **client-side**: nessun dato lascia il tuo browser.

## Come usare builder e validatore

1. **Imposta le direttive nel builder** - Ogni direttiva ha un menu a tendina con i valori canonici. La configurazione iniziale è già una baseline sicura: `default-src 'self'`, script e style dalla sola origine, `frame-ancestors 'none'` contro il clickjacking. Restringi con `'none'` ciò che non ti serve, allenta solo dove l'applicazione lo richiede davvero.
2. **Aggiungi host fidati e opzioni** - Nel campo host aggiuntivi elenca i domini di terze parti legittimi (il CDN degli script, l'endpoint delle API). Attiva `upgrade-insecure-requests` se hai risorse http:// residue, e imposta `report-uri` per raccogliere le violazioni. La modalità report-only genera l'header di collaudo che osserva senza bloccare.
3. **Genera e copia l'header** - Il pulsante Genera produce l'header `Content-Security-Policy` completo, pronto da incollare nella configurazione di Apache, Nginx o del middleware applicativo. Copia con un click. Se hai scelto un valore con nonce, sostituisci `{NONCE}` con il token casuale che il tuo server genera a ogni request.
4. **Valida una policy esistente** - Incolla nel validatore la CSP che stai già servendo (o l'header intero copiato da `curl -I`). Il report evidenzia in tempo reale ciò che indebolisce la protezione, assegna una severità a ogni finding e calcola un punteggio di hardening indicativo. Correggi nel builder e rigenera.

## Perché la CSP è la difesa a costo zero contro l'XSS

**Cosa fa davvero.** La Content-Security-Policy è un header HTTP di risposta che dice al browser da quali origini può caricare ed eseguire risorse: script, stili, immagini, font, frame, connessioni di rete. È una allowlist dichiarativa. Con `script-src 'self'` il browser esegue solo il JavaScript servito dal tuo dominio e rifiuta tutto il resto, compreso il payload che un attaccante riesce a iniettare tramite un cross-site scripting. La CSP non ripara la vulnerabilità di injection a monte, ma neutralizza la fase di sfruttamento: lo script iniettato semplicemente non parte. È difesa in profondità che costa zero performance e si attiva con una riga di configurazione.

**La trappola di 'unsafe-inline'.** Il modello di sicurezza della CSP si regge su una distinzione: il codice che arriva da una sorgente fidata gira, quello inline (dentro `<script>` o negli attributi `onclick=`) no, perché il browser non può distinguere l'inline legittimo da quello iniettato. Aggiungere `'unsafe-inline'` a `script-src` riapre esattamente la porta che la CSP doveva chiudere: qualunque payload iniettato torna eseguibile e la protezione XSS si azzera. Le alternative moderne sono tre: un **nonce** casuale per request marcato sui soli script legittimi, un **hash** SHA-256 del contenuto inline atteso, oppure `'strict-dynamic'` che propaga la fiducia dagli script con nonce a quelli che caricano dinamicamente, liberandoti dal mantenere una lista di host.

**Builder e validatore, un flusso solo.** Il builder parte da una baseline volutamente restrittiva perché nella CSP la sicurezza è il default e l'apertura è l'eccezione da giustificare. Comporre la policy scegliendo i valori evita gli errori di sintassi (un punto e virgola di troppo, una direttiva scritta male) che rendono la CSP silenziosamente inefficace. Il validatore chiude il cerchio sull'esistente: incolli la policy che già servi e vedi subito se un `*`, un `data:` in `script-src` o l'assenza di `default-src` stanno lasciando una falla. Nessuno dei due strumenti contatta la rete.

**Report-only prima di enforce.** Applicare una CSP stretta a un sito vivo senza collaudo rompe risorse legittime. Per questo esiste `Content-Security-Policy-Report-Only`: la policy viene valutata e ogni violazione è registrata e inviata al tuo `report-uri`, ma nulla viene bloccato. Si osserva per giorni o settimane il traffico reale, si raffina la policy sui report, e solo quando i falsi positivi sono a zero si passa all'header che blocca. Privacy per costruzione: builder e validatore girano interamente nel browser, il sito che stai proteggendo non viene mai contattato dai nostri server, quindi puoi lavorare anche su ambienti di staging e intranet non esposti.

## Glossario

- **CSP (Content-Security-Policy)**: Header HTTP di risposta che dichiara al browser quali sorgenti sono autorizzate per ciascun tipo di risorsa. Difesa primaria contro XSS e data injection. Standardizzata da W3C in CSP Level 3.
- **Direttiva**: Singola regola della policy, nella forma `nome-direttiva sorgenti` (es. `script-src 'self'`). Le direttive sono separate da punto e virgola all'interno dell'header.
- **Source list**: L'elenco di sorgenti che segue una direttiva. Può contenere keyword tra apici (`'self'`, `'none'`), schemi (`https:`, `data:`), host (`https://cdn.example.com`) e wildcard.
- **Nonce**: Number used once. Token casuale e imprevedibile generato dal server a ogni request, inserito nella direttiva come `'nonce-...'` e come attributo `nonce` sui soli script legittimi. Rende sicuro l'inline senza allowlist di host.
- **Hash**: Digest crittografico (SHA-256, SHA-384, SHA-512) del contenuto esatto di uno script o stile inline, dichiarato come `'sha256-...'`. Il browser esegue l'inline solo se il suo hash combacia. Alternativa statica al nonce.
- **strict-dynamic**: Keyword che propaga la fiducia: gli script caricati da uno script già fidato (con nonce o hash) sono autorizzati a loro volta, ignorando host e wildcard nella policy. Semplifica le CSP con caricamento dinamico di moduli.
- **frame-ancestors**: Direttiva che stabilisce quali origini possono incorporare la pagina in un `<frame>` o `<iframe>`. Con `'none'` è la difesa contro il clickjacking, più espressiva di X-Frame-Options.
- **report-uri / report-to**: Direttive che indicano dove il browser invia i report JSON delle violazioni CSP. `report-uri` è la forma storica ancora supportata; `report-to` è il successore moderno basato sul Reporting API. Essenziali per collaudare in report-only.

## Domande frequenti sulla CSP

### Cosa fa esattamente la Content-Security-Policy?

Dice al browser da quali origini è lecito caricare ed eseguire ogni tipo di risorsa (script, stili, immagini, frame, connessioni). Tutto ciò che non rientra nella allowlist viene bloccato. Il beneficio principale è contro l'XSS: anche se un attaccante riesce a iniettare del codice nella pagina, con una `script-src` stretta quel codice non viene eseguito dal browser.

### I miei dati restano nel browser?

Sì, interamente. Sia il builder sia il validatore girano in JavaScript nel tuo browser. La policy che componi o incolli non viene inviata ad alcun server, e il sito che stai proteggendo non viene mai contattato dalla nostra infrastruttura. Puoi usare il tool anche offline e su ambienti di staging o intranet non raggiungibili dall'esterno.

### Che differenza c'è tra report-only ed enforce?

L'header `Content-Security-Policy` applica la policy: le risorse fuori dalla allowlist vengono bloccate davvero. L'header `Content-Security-Policy-Report-Only` valuta la stessa policy ma non blocca nulla: registra soltanto le violazioni e le invia al `report-uri`. Report-only è il modo corretto di collaudare una CSP su un sito in produzione prima di attivarla, così da scoprire i falsi positivi senza rompere l'esperienza degli utenti.

### Cosa è un nonce e come lo uso?

Un nonce è un token casuale, diverso a ogni caricamento di pagina, generato dal tuo server. Lo inserisci nella direttiva come `script-src 'nonce-r4nd0m'` e come attributo sui tag che vuoi autorizzare: `<script nonce="r4nd0m">`. Il browser esegue solo gli inline che portano il nonce corrente. Poiché l'attaccante non può prevedere il valore, il suo script iniettato non lo avrà e resterà bloccato. È l'alternativa sicura a `'unsafe-inline'`.

### 'unsafe-inline' è davvero così pericoloso?

Sì, su `script-src` vanifica la protezione. La CSP funziona proprio perché distingue il codice fidato dall'inline arbitrario; `'unsafe-inline'` dice al browser di eseguire qualunque script inline, compreso quello iniettato da un XSS. In pratica riporti la pagina allo stato di partenza. Se hai molti `onclick=` legacy, migra gradualmente a nonce, hash oppure ad addEventListener in JavaScript esterno, invece di lasciare la direttiva aperta.

### Come impedisco che il mio sito venga caricato in un iframe (clickjacking)?

Con `frame-ancestors 'none'` nella CSP: nessuna pagina, di nessuna origine, potrà incorporare la tua in un frame o iframe. Se vuoi consentire solo la tua stessa origine, usa `frame-ancestors 'self'`. Questa direttiva è più espressiva e affidabile del vecchio header X-Frame-Options, che copriva solo i casi DENY e SAMEORIGIN; averla è la difesa moderna contro il clickjacking.

### default-src copre tutte le altre direttive?

Solo le direttive di fetch che non hai dichiarato esplicitamente. `default-src` è il fallback per `script-src`, `style-src`, `img-src`, `connect-src`, `font-src` e simili quando queste mancano. Attenzione però: alcune direttive importanti NON ricadono sotto default-src, in particolare `frame-ancestors`, `base-uri` e `form-action`. Vanno sempre dichiarate a parte, altrimenti restano prive di restrizioni anche con un default-src stretto.

### Come applico la CSP: header HTTP o meta tag?

L'header HTTP è la via consigliata: `add_header Content-Security-Policy "...";` in Nginx, `Header set Content-Security-Policy "..."` in Apache, oppure un middleware nel framework applicativo. In alternativa puoi usare `<meta http-equiv="Content-Security-Policy" content="...">` nell'HTML, ma il meta tag ha limiti: non supporta `frame-ancestors` né `report-uri` e va posizionato prima di qualsiasi risorsa. Per una protezione completa usa l'header.

### Cosa è 'strict-dynamic' e quando conviene?

È una keyword che propaga la fiducia: se uno script autorizzato con nonce ne carica dinamicamente altri, questi ereditano l'autorizzazione senza bisogno di elencare i loro host nella policy. Conviene sulle applicazioni moderne con bundler e caricamento dinamico di moduli, dove mantenere una allowlist di domini sarebbe fragile. In presenza di `'strict-dynamic'` gli host e le wildcard nella stessa direttiva vengono ignorati dai browser che la supportano.

### Come testo una CSP senza rompere il sito?

Parti in report-only con un `report-uri` attivo e osserva le violazioni reali generate dal traffico degli utenti per qualche giorno. Ogni report indica la direttiva violata e la risorsa bloccata: usali per allargare la policy solo dove serve davvero, preferendo nonce e host specifici alle wildcard. Quando il flusso di violazioni legittime si azzera, sostituisci l'header report-only con quello che blocca. Rigenera la versione finale nel builder e rivalidala prima del deploy.

---
Uno strumento di Maurizio Fonte, senior backend engineer. Tutti gli strumenti: https://www.mauriziofonte.it/strumenti/
