• v1.4.0 e6318956de

    v1.4.0
    All checks were successful
    Auto Release on version bump / release (push) Successful in 8s
    Stable

    Ghost released this 2026-10-03 18:01:03 +02:00 | 5 commits to main since this release

    Revisione anti-spam dopo un messaggio di prova (03/10/2026) passato da tutte le difese: lo stesso marcatore 169954 in Nome, Oggetto e Messaggio, email su dominio usa-e-getta. Lo scopo era verificare quali campi la risposta automatica rimanda a un indirizzo scelto da chi scrive: Nome e Oggetto tornavano indietro, quindi il form poteva fare da relay di spam con mittente noreply@ del sito (già successo il 21/09 con un messaggio pubblicitario e la conferma recapitata a un indirizzo di terzi). Nei log NPM di un mese: 873 POST al form, il 95% fermato dal solo tempo minimo; lo spam passato aspettava 5-19 secondi.

    Changed

    • Risposta automatica a testo fisso: niente più Nome né Oggetto del mittente. Parte al massimo 1 volta al giorno per indirizzo e 10 volte all'ora su tutto il sito, e mai per i messaggi sospetti.
    • Rate limit solo su REMOTE_ADDR: Client-IP e X-Forwarded-For li imposta il client e permettevano di azzerare il contatore. Dietro un reverse proxy l'IP reale va ripristinato dal web server (in produzione lo fa già mod_remoteip nel container WordPress).
    • Il rate limit conta anche i tentativi falliti (10/h per IP) oltre agli invii riusciti (3/h). Con un object cache persistente (Redis) l'incremento è atomico; le chiavi contengono la finestra temporale, quindi un contatore non sopravvive alla sua ora anche se la cache perde la scadenza.
    • Nonce, token scaduto o già usato: niente più wp_die() di check_admin_referer(), il form ricompare con il testo scritto e un token nuovo. Per i visitatori anonimi il nonce è condiviso e dura 12-24 h, quindi non è una difesa anti-bot.
    • Honeypot: nome eg_contact_ref, etichetta neutra, contenitore con aria-hidden (prima uno screen reader lo leggeva e poteva farlo compilare).
    • Il template riceve i valori già sanitizzati da render_form() invece di rileggere $_POST; niente più $_POST = array().
    • L'invio viene elaborato una sola volta per richiesta anche se lo shortcode viene renderizzato più volte.

    Added

    • Token firmato (HMAC con wp_salt( 'nonce' )) con ora di emissione e id casuale: tempo minimo 5 s, età massima 6 h, uso singolo (consumato solo quando la mail parte). Sostituisce il campo eg_timestamp, che non era firmato e, se assente, valeva 0 e superava il controllo.
    • Quarantena: un messaggio con punteggio >= 2 arriva comunque al destinatario con [SUSPECT: motivi] nell'oggetto e un avviso nel corpo, senza risposta automatica. Segnali: stessa sequenza di 5 caratteri con almeno una cifra in Nome, Oggetto e Messaggio (2 punti); messaggio sotto le 3 parole; Nome con URL, @ o 4 cifre; URL nell'Oggetto; Nome o Oggetto di una sola parola di 15+ caratteri con lettere e cifre; campi identici (1 punto ciascuno). Il probe del 03/10 fa 5 punti. La regola della sequenza ripetuta richiede una cifra perché senza scattava su messaggi veri (nome ripetuto nella firma e nell'oggetto).
    • Contatori giornalieri (giorni UTC) per esito nell'opzione eg_contact_stats (autoload off), 30 giorni, senza IP né contenuti: sent, quarantined, honeypot, too_fast, token_invalid, token_expired, token_used, nonce, rate_attempts, rate_sends, invalid, mail_error, autoreply_limited.
    • Pagine con lo shortcode escluse dalla cache di pagina (DONOTCACHEPAGE + nocache_headers() su template_redirect): con una cache il token sarebbe uguale per tutti e il secondo visitatore lo troverebbe già usato.

    Fixed

    • Reply-To: virgole, punti e virgola, virgolette e parentesi angolari tolti dal Nome. wp_mail() divide il Reply-To sulle virgole e un Nome come x@altro.tld, Mario aggiungeva un indirizzo.
    • Lunghezze dei campi con mb_strlen(): prima un nome non latino di 51 caratteri superava il limite di 100 byte.
    • EG_CONTACT_VERSION allineata all'header (era ferma a 1.3.1).
    • Disattivazione e disinstallazione: DELETE con $wpdb->prepare() ed esc_like(), su tutti i transient eg_contact_*; la disinstallazione cancella anche eg_contact_stats.
    • readme.txt: Tested up to 7.1; tolta la voce sul "confirmation link token", che non corrispondeva a nessuna funzione.

    Notes

    • Le nuove chiavi tengono il prefisso eg_contact_ per coerenza con l'opzione esistente; il passaggio al prefisso con lo slug completo richiede una migrazione ed è rimandato.
    • Collaudo: test nel container con object cache in memoria, mail intercettate da pre_wp_mail e scritture DB bloccate (token, limiti, spoofing Client-IP, quarantena del probe, limiti auto-reply, Reply-To, nomi cirillici, 4 messaggi legittimi non segnalati).

    Downloads