Gli header di risposta HTTP indicano al browser come trattare le pagine: quali script possono essere eseguiti, se il sito può essere incorporato in un frame e se deve essere caricato sempre tramite HTTPS. Alcuni di essi bloccano intere classi di attacchi a costo quasi nullo. Altri sono obsoleti e aggiungono solo rumore, o addirittura rischi.
Una base da cui partire
Questo è un punto di partenza ragionevole per un’applicazione HTML servita solo tramite HTTPS. Non lo incolli così com’è. In particolare, la CSP deve corrispondere al modo in cui le sue pagine caricano gli script, il suo nonce deve essere nuovo per ogni risposta, e il preload HSTS è difficile da annullare.
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Content-Security-Policy: script-src 'nonce-3f9a1c7e2b' 'strict-dynamic'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=(), microphone=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-site
Content-Security-Policy
La CSP limita le origini da cui possono provenire script e altre risorse. Il suo compito principale è rendere molto più difficile sfruttare il cross-site scripting (XSS).
Il cheat sheet OWASP sulla CSP privilegia una policy rigorosa (strict) basata su nonce o hash rispetto a un lungo elenco di domini consentiti. Le policy basate su allowlist troppo ampie o troppo dettagliate tendono a essere aggirate. Una policy basata su nonce ha questo aspetto:
Content-Security-Policy: script-src 'nonce-3f9a1c7e2b' 'strict-dynamic'; object-src 'none'; base-uri 'none'
Ogni tag script riporta quindi lo stesso valore, come in <script nonce="3f9a1c7e2b">. Il nonce deve essere casuale e nuovo per ogni risposta; un valore fisso ne vanifica lo scopo. Lo generi nel livello di templating. OWASP sconsiglia i middleware che aggiungono il nonce a ogni tag script, perché legittimerebbero anche gli script iniettati.
Se le pagine sono statiche, usi invece gli hash: valori 'sha256-...' per ogni script inline. Qualsiasi modifica allo script, anche solo agli spazi, cambia l’hash.
Eviti 'unsafe-inline' e 'unsafe-eval' in script-src. Riaprono esattamente ciò che la CSP dovrebbe chiudere.
Per introdurla senza rompere nulla, invii prima la policy come Content-Security-Policy-Report-Only. I browser segnalano le violazioni senza bloccare nulla. Corregga ciò che emerge dai report, poi passi all’applicazione.
Trusted Types
I Trusted Types contrastano l’XSS basato sul DOM, in cui il suo stesso JavaScript passa stringhe controllate dall’attaccante ad API pericolose come innerHTML, eval() o la proprietà src di un elemento script. Si attivano con la CSP:
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types app-policy
Con l’applicazione attiva, passare una semplice stringa a uno di questi sink genera un errore. Il codice deve passare valori creati da una policy con nome, di solito una che sanifica l’HTML. MDN indica l’API come Baseline da febbraio 2026, cioè funzionante nelle versioni attuali dei principali browser. Inizi in modalità report-only, perché il codice esistente potrebbe scrivere stringhe direttamente nel DOM.
Strict-Transport-Security e preload
HSTS indica ai browser di connettersi al dominio solo tramite HTTPS, per il numero di secondi indicato in max-age. Con includeSubDomains, la regola copre anche ogni sottodominio.
L’elenco di preload va oltre. I browser includono l’elenco al loro interno, quindi anche la prima visita al dominio usa HTTPS. I requisiti indicati su hstspreload.org sono:
- un certificato valido e un reindirizzamento da HTTP a HTTPS sullo stesso host
- tutti i sottodomini serviti tramite HTTPS, compresi quelli interni
max-agedi almeno 31536000 (un anno), piùincludeSubDomainsepreload- l’header HSTS anche sui reindirizzamenti serviti dal sito HTTPS
Proceda per fasi. Il sito del preload suggerisce di iniziare con max-age=300, poi una settimana (604800), poi un mese (2592000), verificando a ogni passo che nulla si rompa. La rimozione dall’elenco di preload impiega mesi per raggiungere gli utenti, quindi si assicuri che ogni sottodominio possa supportare HTTPS a lungo termine.
X-Content-Type-Options
X-Content-Type-Options: nosniff impedisce ai browser di indovinare il tipo di un file dal suo contenuto. Lo abbini a un Content-Type corretto su ogni risposta, compreso un charset per l’HTML, ad esempio text/html; charset=UTF-8.
frame-ancestors e X-Frame-Options
Il clickjacking funziona caricando la sua pagina in modo invisibile all’interno di un frame su un altro sito. La direttiva CSP frame-ancestors controlla chi può incorporarla in un frame, e OWASP osserva che sostituisce X-Frame-Options nei browser che la supportano.
Due dettagli sfuggono spesso. Secondo MDN, frame-ancestors non ricade su default-src, quindi va impostata esplicitamente. Inoltre non ha effetto in un tag <meta>: funziona solo come header. Per i browser più vecchi, inviare entrambi non fa danni:
Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY
Usi frame-ancestors 'self' se il suo sito incorpora le proprie pagine in frame. Eviti X-Frame-Options: ALLOW-FROM, che è obsoleto. MDN osserva che i browser moderni ignorano l’intero header quando lo incontrano.
Referrer-Policy
Questo header controlla quanta parte dell’URL corrente viene inviata ad altri siti nell’header Referer. Se non si imposta nulla, i browser usano per impostazione predefinita strict-origin-when-cross-origin, che invia ad altri siti solo l’origine, tramite HTTPS. OWASP raccomanda comunque di impostarlo esplicitamente. Usi no-referrer o same-origin se i suoi URL possono contenere token o dati personali.
Permissions-Policy
Permissions-Policy disattiva le funzioni del browser che il sito non usa. Una allowlist vuota, (), disattiva una funzione per la pagina e per ogni frame al suo interno:
Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=()
Se una funzione serve, la consenta in modo mirato, ad esempio camera=(self).
COOP e CORP
Cross-Origin-Opener-Policy: same-origin colloca la pagina in un proprio gruppo di contesti di navigazione. Una pagina che apre la sua con window.open() non può quindi mantenerne un riferimento, il che chiude una classe di attacchi di tipo cross-site leak (XS-Leaks). Se usa popup per il single sign-on o i pagamenti, same-origin-allow-popups li mantiene funzionanti.
Cross-Origin-Resource-Policy: same-site impedisce ad altri siti di incorporare le sue risorse, come immagini o script. Cross-Origin-Embedder-Policy: require-corp serve solo per l’isolamento cross-origin, richiesto da funzioni come SharedArrayBuffer. Ometta COEP a meno che non le servano quelle funzioni, perché blocca le risorse cross-origin che non lo consentono esplicitamente.
Header da abbandonare
| Header | Stato | Cosa fare |
|---|---|---|
X-XSS-Protection | Deprecato e non standard; MDN avverte che può creare vulnerabilità XSS in siti altrimenti sicuri | Rimuoverlo, oppure inviare 0, e affidarsi alla CSP |
Expect-CT | Deprecato | Rimuoverlo |
Public-Key-Pins | Rimosso da Chromium nel 2018 | Rimuoverlo; usare invece Certificate Transparency e record CAA |
X-Frame-Options: ALLOW-FROM | Obsoleto | Usare frame-ancestors |
Server, X-Powered-By | Rivelano software e versioni | Rimuoverli o usare un valore neutro |
Da dove iniziare
- Verifichi cosa invia oggi il suo sito con il nostro scanner degli header di sicurezza.
- Aggiunga prima gli header a basso rischio:
X-Content-Type-Options,Referrer-Policy,Permissions-Policyeframe-ancestors. - Attivi HSTS con un
max-agebreve e lo aumenti per fasi. Valuti il preload solo quando tutti i sottodomini sono pronti. - Usi la CSP in modalità report-only per qualche settimana, corregga le violazioni, poi la applichi.
Se sta sviluppando una nuova applicazione e vuole che queste protezioni siano previste fin dall’inizio, il nostro team di sviluppo di software sicuro può aiutarla.
