Guida di risoluzione

Come configurare gli header HTTP di sicurezza via .htaccess vs Nginx

20 maggio 2026

Gli header HTTP di sicurezza sono header di risposta che dicono ai browser di applicare comportamenti di sicurezza specifici quando rendono una pagina. Sono configurati sul server web, non in WordPress, e non costano performance da abilitare. Un sito WordPress con header corretti blocca clickjacking, downgrade a contenuto misto, exploit di MIME-sniffing, e una grande quota di payload di cross-site scripting. Il setup è una modifica una tantum nel .htaccess di Apache o nella config server di Nginx. Sotto ci sono i sette header che contano nel 2026, con snippet pronti al copia-incolla per entrambi i server web.

Quali header HTTP di sicurezza dovrebbe impostare un sito WordPress?

Sette header coprono il modello di minaccia realistico per un sito content-driven. In ordine di priorità:

  • Strict-Transport-Security (HSTS). Forza i browser a usare HTTPS per un anno (o più) dopo la prima visita, prevenendo attacchi di HTTPS-stripping su WiFi pubblico. Obbligatorio se il tuo sito ha utenti loggati.
  • Content-Security-Policy (CSP). Dice al browser esattamente quali fonti di JavaScript, CSS, immagini e font sono permesse. L'header più d'impatto contro XSS, ma anche il più tricky da configurare senza rompere il sito.
  • X-Frame-Options o la direttiva CSP frame-ancestors. Impedisce che il tuo sito venga embedded in un iframe su un altro dominio, bloccando attacchi di clickjacking contro il form di login.
  • X-Content-Type-Options: nosniff. Ferma i browser dall'indovinare il content type di una risposta, chiudendo una classe di attacchi "carica un'immagine fasulla che è in realtà JavaScript".
  • Referrer-Policy. Controlla quanto dell'URL corrente viene inviato nell'header Referer sui click in uscita. I default fanno trapelare le query string a terze parti; strict-origin-when-cross-origin è la raccomandazione moderna.
  • Permissions-Policy (precedentemente Feature-Policy). Disabilita funzionalità del browser che il tuo sito non usa (camera, microfono, geolocalizzazione), riducendo l'esposizione se uno script di terze parti tenta mai di accedervi.
  • Cross-Origin-Opener-Policy. Isola il tuo sito da qualsiasi popup che apre, mitigando attacchi side-channel classe Spectre. Richiesto perché SharedArrayBuffer funzioni.

Cosa non è più raccomandato: X-XSS-Protection (deprecato, i browser lo ignorano), Public-Key-Pins (deprecato, ha causato troppi lockout) ed Expect-CT (deprecato dal 2023).

Apache .htaccess: blocco copia-incolla per header di sicurezza

Aggiungi questo in cima al tuo .htaccess nella root WordPress, sopra il blocco WordPress (# BEGIN WordPress). La guardia IfModule assicura che lo snippet non crashi se manca mod_headers.

<IfModule mod_headers.c>
    # HSTS: forza HTTPS per 1 anno, includi sottodomini, preload-ready
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

    # Previeni clickjacking
    Header always set X-Frame-Options "SAMEORIGIN"

    # Blocca MIME-sniffing
    Header always set X-Content-Type-Options "nosniff"

    # Limita la fuga del referrer
    Header always set Referrer-Policy "strict-origin-when-cross-origin"

    # Disabilita funzionalità del browser non usate
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()"

    # Isolamento cross-origin
    Header always set Cross-Origin-Opener-Policy "same-origin"

    # CSP iniziale conservativa; stringi una volta che sai cosa il sito carica
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self' https:; frame-ancestors 'self'; base-uri 'self'; form-action 'self';"
</IfModule>

La parola chiave always è critica. Senza, gli header vengono inviati solo sulle risposte 2xx e 3xx; con essa, anche le pagine di errore e i redirect portano gli header. Senza always, un attaccante che innesca un errore 500 vede una risposta non protetta.

Il modulo mod_headers deve essere abilitato. Su hosting condiviso di solito lo è già. Su un Apache autogestito: sudo a2enmod headers && sudo systemctl reload apache2.

Nginx: blocco copia-incolla per header di sicurezza

Aggiungi questo all'interno del blocco server { ... } del tuo sito, tipicamente in /etc/nginx/sites-available/tuosito.conf:

    # HSTS: forza HTTPS per 1 anno, includi sottodomini, preload-ready
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Previeni clickjacking
    add_header X-Frame-Options "SAMEORIGIN" always;

    # Blocca MIME-sniffing
    add_header X-Content-Type-Options "nosniff" always;

    # Limita la fuga del referrer
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Disabilita funzionalità del browser non usate
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" always;

    # Isolamento cross-origin
    add_header Cross-Origin-Opener-Policy "same-origin" always;

    # CSP iniziale conservativa; stringi una volta che sai cosa il sito carica
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self' https:; frame-ancestors 'self'; base-uri 'self'; form-action 'self';" always;

L'always finale in Nginx serve allo stesso scopo che in Apache: fa applicare l'header anche alle risposte di errore. Ricarica Nginx dopo il cambio: sudo nginx -t && sudo systemctl reload nginx.

La regola dei due tranelli di Nginx add_header

Nginx ha una peculiarità che morde la gente ripetutamente. Due regole da interiorizzare prima di toccare la config di produzione:

  • add_header è sostituito, non unito. Se imposti header nel blocco server e di nuovo in un blocco location, gli header del blocco location sostituiscono quelli del blocco server per quella location. Non si sommano. Il sintomo: gli header funzionano ovunque tranne all'interno di una location specifica (come /wp-admin/ dove hai aggiunto una regola custom).
  • Aggiungi sempre il flag always. Senza, una pagina 404 o una pagina di errore 500 viene servita senza i tuoi header di sicurezza. Gli attaccanti possono deliberatamente innescare errori per bypassare le protezioni basate su header.

L'Header always set di Apache è l'equivalente del flag always di Nginx e ha lo stesso effetto.

Apache vs Nginx: quale è più facile da configurare?

Praticamente equivalenti per gli header di sicurezza. Entrambi usano una singola direttiva per header e accettano valori di header identici. Tre differenze degne di nota:

  • Dove vive la config. Apache via .htaccess può essere modificato per-directory da chiunque abbia accesso FTP all'installazione WordPress. La config Nginx vive fuori dal document root e di solito richiede SSH più un reload. Per hosting WordPress condiviso, .htaccess è più pratico; per setup Nginx managed, la config server è più performante (Nginx non rilegge le regole equivalenti a .htaccess ad ogni richiesta, ma tiene la config nginx corretta in memoria).
  • Override per location. Apache .htaccess eredita automaticamente le impostazioni della directory parent. I blocchi location di Nginx richiedono ridichiarazione esplicita se ne customizzi uno (a causa del tranello del merge sopra).
  • Realtà dell'hosting. La maggior parte dell'hosting WordPress condiviso (Hostinger, IONOS, GoDaddy, host cPanel tradizionali) è Apache. La maggior parte dell'hosting WordPress managed (Kinsta, WP Engine, Raidboxes, SiteGround, Cloudways) è Nginx. La quota di mercato è passata da maggioranza-Apache a circa 50/50 negli ultimi cinque anni.

Dovrei aggiungere gli header di sicurezza in WordPress invece che nel server web?

Puoi, ma il livello server web è meglio. Esistono tre opzioni lato WordPress:

  • Plugin di sicurezza (Wordfence, iThemes Security, ecc.). Ha una funzionalità "header di sicurezza" che aggiunge gli stessi header lato PHP. Funziona ma aggiunge qualche millisecondo per richiesta. Utile se non hai accesso al server web.
  • Codice custom di plugin o tema. Un piccolo mu-plugin può chiamare header() in PHP per emettere ogni header. Stesso overhead, stessi caveat.
  • Config server web (raccomandato). Zero overhead PHP, si applica a ogni risposta inclusi errori 404 e file statici, sopravvive ai crash di WordPress.

L'argomento per il livello server web: gli header aggiunti in PHP non proteggono le risposte che bypassano PHP. Se un attaccante raggiunge un file statico direttamente (un backup .phps dimenticato, una directory di upload con file HTML), gli header impostati da PHP non vengono applicati. Il server web vede ogni richiesta ed è il layer corretto.

Come affino la Content-Security-Policy senza rompere il mio sito?

CSP è l'header di sicurezza più d'impatto e anche il più probabile a rompere cose. Un sito WordPress carica script e style da decine di fonti di default: jQuery da /wp-includes, asset del tema, asset dei plugin, Google Fonts (se non self-hosted), analytics, YouTube embedded, ecc. Una CSP rigida che non whitelista queste esplicitamente le bloccherà e il sito apparirà rotto in modi sottili (il login fallisce, la galleria non funziona, l'analytics si ferma).

Il pattern di rollout in due fasi che funziona:

  1. Inizia in modalità report-only. Usa Content-Security-Policy-Report-Only invece di Content-Security-Policy. Il browser non blocca nulla; logga solo le violazioni nella console developer. Naviga il tuo sito per qualche giorno, monitora cosa sarebbe stato bloccato, e aggiungi le fonti legittime alla tua policy.
  2. Passa alla modalità enforcing. Una volta che la modalità report-only mostra zero violazioni su una navigazione normale, cambia il nome dell'header di nuovo a Content-Security-Policy. Ora le violazioni sono bloccate.

Una trappola comune: WordPress e molti plugin usano handler di eventi JavaScript inline (onclick="") e blocchi <script> inline. Una CSP rigida richiede o 'unsafe-inline' (sconfigge la maggior parte della protezione) o nonce per ogni script inline (cambiamenti significativi di codice). Il giusto compromesso pragmatico nel 2026: mantieni 'unsafe-inline' per ora, ma stringi le altre direttive. Le future versioni di WordPress si muovono verso script inline nonce-friendly.

Come verifico che i miei header di sicurezza funzionino?

Quattro metodi, dal più veloce al più autorevole:

  1. Report InspectWP. La sezione Sicurezza elenca ogni header che il tuo sito imposta, il suo valore, e segnala quelli mancanti o configurati male. Una schermata.
  2. curl da riga di comando. curl -I https://tuosito.com stampa gli header di risposta. Cerca i sette header sopra; verifica i loro valori.
  3. securityheaders.com. Uno scanner pubblico gratuito che dà un voto al tuo sito (A+ a F) e spiega quali header mancano o sono deboli. Standard del settore per gli audit di header.
  4. DevTools del browser. Apri DevTools (F12), tab Network, clicca sulla richiesta del documento, guarda la sezione Response Headers. Utile per vedere le violazioni CSP live nel tab Console.

Errori e trappole comuni

  • Aggiungere HSTS senza confermare che HTTPS funzioni su tutto il sito. HSTS forza i browser a usare HTTPS per un anno. Se il tuo sito ha un certificato rotto o una sottopagina che funziona solo su HTTP, gli utenti restano bloccati fuori. Testa HTTPS a fondo prima di abilitare HSTS. Inizia con un max-age corto (tipo 300 secondi) e sali fino a un anno.
  • Impostare X-Frame-Options E CSP frame-ancestors. Entrambi funzionano ma frame-ancestors è l'equivalente moderno. Impostarli entrambi è ridondante ma innocuo; i browser moderni preferiscono frame-ancestors.
  • Dimenticare includeSubDomains in HSTS. Se il tuo sito principale è HTTPS ma un sottodominio serve ancora HTTP, gli attaccanti possono pivotare attraverso il sottodominio. includeSubDomains forza HTTPS ovunque sotto il tuo dominio. Verifica che tutti i sottodomini siano HTTPS prima di aggiungere questo.
  • Copiare una CSP da un tutorial generico. Ogni sito WordPress carica asset di terze parti diversi. Una CSP generica romperà il tuo sito. Usa prima la modalità report-only.
  • Mescolare header CDN e origin. Se hai Cloudflare davanti, puoi impostare header su Cloudflare (Page Rules o Transform Rules) o all'origin. Impostare entrambi con valori diversi causa confusione nel debug. Scegli un posto e documentalo.
  • Dimenticare di ricaricare dopo la modifica. I cambi Nginx non fanno nulla fino a systemctl reload nginx. I cambi .htaccess Apache sono istantanei; i cambi della config principale Apache richiedono un reload.

E HTTP/3 e la storia moderna degli header?

HTTP/3 non cambia nulla su quali header impostare; la semantica degli header è identica tra HTTP/1.1, HTTP/2 e HTTP/3. Un header che diventa rilevante su HTTP/3 è Alt-Svc, che pubblicizza la disponibilità di HTTP/3 ai client arrivati su HTTP/2. La maggior parte dei server web lo aggiunge automaticamente.

Il panorama dei browser si sta anche gradualmente muovendo verso l'applicazione di default moderni anche quando gli header mancano. Chrome e Firefox ora defaultano a strict-origin-when-cross-origin per Referrer-Policy se nessun header viene inviato, e sempre più assumono HTTPS per qualsiasi sito che sia mai stato servito su HTTPS. Impostare gli header esplicitamente è ancora raccomandato perché i default variano per versione del browser e perché i client HTTP non-browser (curl, script, strumenti di monitoring) non implementano questi default.

Cosa controlla InspectWP

La sezione Sicurezza di ogni report InspectWP ispeziona gli header di risposta del tuo documento principale e riporta quali degli header di sicurezza standard sono presenti, quali sono i loro valori, e quali mancano o sono impostati a valori non raccomandati. HSTS mancante su un sito HTTPS è segnalato come avvertimento; X-Content-Type-Options mancante è segnalato come informativo; una CSP impostata a default-src * (effettivamente nessuna policy) è segnalata come configurazione errata. Il report nota anche quando gli header sono impostati a livello CDN versus a livello origin, perché ciò influenza cosa dovresti cambiare per aggiornarli. Lo stato raccomandato è tutti e sette gli header presenti con valori ragionevoli, e CSP o in modalità report-only mentre la affini o in modalità enforcing una volta affinata.

Controlla subito il tuo sito WordPress

InspectWP analizza il tuo sito WordPress per problemi di sicurezza, problemi SEO, conformità GDPR e prestazioni — gratuitamente.

Analizza gratis il tuo sito