Il 20 settembre 2026 ho chiesto a lucarimediotti.com/.well-known/security.txt di rispondere: ha restituito 404 con la pagina di errore del tema, text/html, 60 KB di markup. Lo stesso dominio dove scrivo di sicurezza non dice a nessuno dove segnalare un problema. Non è un caso isolato: è la configurazione predefinita di ogni installazione WordPress, e nella settimana in cui Intel ha sospeso un bug bounty che pagava da 500 a 100.000 dollari a segnalazione quel silenzio costa più di prima.
Perché adesso il canale serve davvero
La ricerca di vulnerabilità assistita da AI ha cambiato i volumi, non solo i toni. I CVE del kernel Linux si avvicinano a 2.000 per release contro i circa 500 di prima, con i manutentori dichiaratamente sommersi; il programma Internet Bug Bounty di HackerOne ha sospeso le nuove submission dal 27 marzo, motivandolo con l’espansione di copertura e velocità portata proprio dalla ricerca assistita. Intel ha spostato la disclosure su una pagina Intigriti senza ricompense. La conseguenza per un sito da PMI non è teorica: quando i canali grandi si chiudono o smettono di pagare, chi scansiona in automatico punta sui bersagli piccoli, e il primo posto dove cerca un contatto è /.well-known/security.txt. Se non lo trova, la segnalazione finisce nel form contatti insieme alle offerte SEO, oppure non arriva affatto e il bug resta aperto finché qualcuno lo usa.
Otto righe e un campo che scade
Il formato è RFC 9116, non una convenzione di buon senso. Due campi sono obbligatori: Contact, che deve essere una URI vera (quindi mailto: o https://, non un indirizzo scritto a mano), e Expires, che deve esserci sempre e comparire una sola volta, in formato RFC 3339, raccomandato entro un anno. Il resto è opzionale e serve a filtrare: Policy dice cosa accetti, Preferred-Languages evita che ti scrivano in una lingua che nessuno in studio legge, Canonical dichiara qual è la copia buona del file se il dominio risponde anche su altri host.
Contact: mailto:[email protected]
Expires: 2027-09-20T12:00:00z
Preferred-Languages: it, en
Policy: https://esempio.it/security-policy/
Canonical: https://esempio.it/.well-known/security.txt
La pagina indicata da Policy vale quanto il file: è lì che chiedi un proof of concept riproducibile e i passi esatti, ed è il filtro che separa una segnalazione utile dall’output grezzo di uno scanner incollato in una mail.
Servirlo su WordPress senza che la 404 se lo mangi
Il percorso è obbligatorio: /.well-known/security.txt, servito in HTTPS con Content-Type: text/plain; charset=utf-8. Una copia in root è ammessa solo per compatibilità e, se ci sono entrambe, vince quella in .well-known. Con Apache basta il file fisico: la rewrite di WordPress lascia passare tutto ciò che esiste su disco. I problemi arrivano altrove — regole Nginx che aprono .well-known solo ad acme-challenge per Let’s Encrypt, deploy che ricreano la webroot e cancellano il file, plugin di sicurezza che vietano le estensioni non previste. Con Nginx il blocco va sciolto in configurazione, perché una richiesta fermata lì non arriva mai a PHP; negli altri casi, se non hai accesso stabile al filesystem, la strada affidabile è servirlo da PHP prima che WordPress decida di essere una 404:
// Serve /.well-known/security.txt come testo, prima del routing del tema.
add_action( 'init', function () {
$uri = wp_unslash( $_SERVER['REQUEST_URI'] ?? '' );
$percorso = (string) wp_parse_url( $uri, PHP_URL_PATH );
if ( '/.well-known/security.txt' !== untrailingslashit( $percorso ) ) {
return;
}
header( 'Content-Type: text/plain; charset=utf-8' );
echo "Contact: mailto:[email protected]\n";
echo "Expires: 2027-09-20T12:00:00z\n";
exit;
} );
La verifica è una riga sola e va fatta dall’esterno, non dal browser loggato: curl -sI https://esempio.it/.well-known/security.txt deve rispondere 200 e text/plain. Un 200 con text/html significa che stai leggendo la pagina di errore del tema, cioè esattamente il problema di partenza.
L’errore che rende il file peggio che inutile
La data. Expires è obbligatorio proprio perché i contatti invecchiano, e un file scaduto dichiara che l’informazione non è più affidabile: chi la legge correttamente smette di fidarsi dell’indirizzo, chi non la legge scrive a una casella dismessa. Metti la scadenza a un anno un promemoria in calendario il mese prima, altrimenti hai spostato il silenzio di dodici mesi più in là. Il secondo errore è indicare una casella che nessuno presidia: info@ gestita da chi filtra preventivi non è un canale di sicurezza, e una segnalazione ignorata per tre settimane diventa una pubblicazione senza preavviso. Il terzo è pensare che il file autorizzi i test: la RFC è esplicita, security.txt non concede alcun permesso a chi vuole provare exploit sul tuo sito. Se vuoi definire cosa è lecito, va scritto nella pagina Policy.
Cosa fare oggi, in ordine
Cinque minuti per dominio, e vale per tutti i siti che gestisci per i clienti, non solo per il tuo. Apri una casella o un alias dedicato e assegnalo a una persona reale. Scrivi il file con Contact ed Expires, caricalo in .well-known o incolla lo snippet nel plugin degli snippet. Verifica con curl -sI che tornino 200 e text/plain. Aggiungi la pagina Policy con la richiesta di proof of concept riproducibile — è la parte che ti risparmia il tempo sprecato sulle segnalazioni automatiche. Metti la scadenza in calendario. Il file non rende il sito più sicuro di un millimetro: rende raggiungibile chi ha già trovato il problema, e oggi quelle persone sono molte più di un anno fa. Per il resto dei file che parlano ai bot resta valido il ragionamento che ho fatto sui content signals nel robots.txt, e sulla casella che riceve le segnalazioni vale la verifica delle mail sospette di cui ho già scritto.

