Quasi ogni WordPress con qualche anno alle spalle ha almeno un plugin che nessuno aggiorna più. È il modulo di prenotazione scelto quando il sito è nato, il connettore verso il gestionale scritto da un piccolo sviluppatore, la galleria che gestisce centinaia di immagini. Finché il sito resta su un PHP vecchio sembra funzionare. Quando si passa a PHP 8, o quando un report di sicurezza segnala una vulnerabilità proprio in quel plugin, la domanda diventa inevitabile: cosa ne facciamo?
In questo articolo vediamo come riconoscere un plugin abbandonato, perché è un rischio anche quando funziona, come capire cosa fa davvero sul sito e quali dati lascia nel database, e come scegliere tra le tre strade possibili: adattarlo, sostituirlo con un’alternativa mantenuta o riscriverne solo la parte che serve.
Come riconoscere un plugin abbandonato
Un plugin può essere fermo da un anno e ancora valido, oppure aggiornato di recente e di fatto senza manutenzione. Nessun segnale da solo basta: conta l’insieme. Quelli da controllare sono pochi.
- Plugin chiuso nella directory ufficiale. Sulla pagina del plugin in wordpress.org compare un avviso che dice che il plugin è stato chiuso e non è più scaricabile, con la data della chiusura. Tra i motivi possibili c’è un problema di sicurezza, e i dettagli di solito non vengono resi pubblici.
- Avviso di plugin non testato. La directory mostra un avviso quando il campo “Tested up to” è più vecchio delle ultime tre versioni principali di WordPress. Non prova l’abbandono, ma indica che l’autore non segue più le release.
- Nessun rilascio da anni e richieste di supporto senza risposta, soprattutto quelle che segnalano errori con PHP 8.
- Plugin a pagamento senza produttore: il sito del venditore non esiste più o non rilascia aggiornamenti per la versione in uso.
- Requisiti fermi: il plugin dichiara compatibilità solo con versioni di PHP e di WordPress fuori supporto.
Le regole degli avvisi sono descritte nella pagina Alerts and Warnings del manuale per gli sviluppatori di plugin. Per un plugin chiuso, la cosa più prudente è considerarlo vulnerabile finché non si dimostra il contrario.
Perché è un rischio anche se funziona
Un plugin è codice PHP che gira con gli stessi permessi di WordPress: legge e scrive nel database, gestisce caricamenti di file, risponde a richieste che arrivano da Internet. Quando qualcuno trova una vulnerabilità in un plugin mantenuto, l’autore pubblica una correzione e gli aggiornamenti la distribuiscono. In un plugin abbandonato la vulnerabilità resta pubblica e aperta, e i plugin diffusi sono tra i primi bersagli delle scansioni automatiche.
Il secondo problema è la compatibilità. Un plugin fermo da anni è stato scritto per PHP 5 o 7 e spesso usa funzioni rimosse in PHP 8, come create_function() ed each(), oppure costrutti che dalla 8.0 sollevano eccezioni. Diventa l’ostacolo che impedisce di aggiornare PHP, e quindi WordPress, come abbiamo descritto nell’articolo su WordPress su PHP vecchio. Disattivarlo non basta: finché i suoi file restano sul server, sono raggiungibili da chi conosce il percorso.
Prima di scegliere: cosa fa davvero il plugin
Spesso nessuno ricorda esattamente a cosa serve un plugin installato anni fa. Prima di decidere bisogna saperlo, perché la scelta dipende da quanto è usato e da quali dati lascia. Le domande sono quattro: quali funzioni del plugin il sito usa davvero, dove compaiono nei contenuti (shortcode, blocchi, widget), quali dati salva e dove, e quali altri componenti dipendono da lui, come un tema che chiama le sue funzioni.
Con WP-CLI le risposte si trovano in pochi minuti su una copia del sito. Nell’esempio il plugin si chiama “vecchioform”: il nome va sostituito con quello reale, così come i prefissi delle opzioni e dei metadati, che si leggono nel suo codice.
# Contenuti pubblicati che usano lo shortcode del plugin
wp db query "SELECT ID, post_type, post_title FROM $(wp db prefix)posts
WHERE post_status = 'publish' AND post_content LIKE '%[vecchioform%'"
# Opzioni salvate dal plugin e tabelle create da lui
wp option list --search='vecchioform_*' --fields=option_name,autoload
wp db tables '*vecchioform*' --all-tables
# Metadati che il plugin associa ai contenuti
wp db query "SELECT meta_key, COUNT(*) FROM $(wp db prefix)postmeta
WHERE meta_key LIKE '\_vecchioform%' GROUP BY meta_key"
# Funzioni del plugin richiamate dal tema
grep -rn 'vecchioform_' wp-content/themes/
Il risultato è una scheda per ogni plugin a rischio: cosa fa, dove è usato, quali dati gestisce e quanto codice contiene. Con questa scheda la scelta diventa quasi sempre evidente.
Prima strada: adattarlo
Adattare significa correggere il codice esistente per renderlo compatibile con PHP 8 e con la versione corrente di WordPress, e chiudere le vulnerabilità note. È la strada giusta quando il plugin è piccolo o medio, il codice è leggibile, non esiste un’alternativa che faccia la stessa cosa e i dati che gestisce sono importanti. La licenza lo permette: i plugin della directory ufficiale sono distribuiti con licenza GPL o compatibile, che consente di modificarli.
Un plugin adattato diventa però codice vostro, da mantenere. Due accorgimenti evitano sorprese. Il primo è cambiarne la versione e dichiarare i nuovi requisiti nell’intestazione. Il secondo è impedire che un aggiornamento dalla directory lo sovrascriva, cosa che può succedere se un giorno qualcuno riprende quel plugin. Dalla versione 5.8 WordPress legge l’intestazione Update URI: con un valore che non punta a wordpress.org, il plugin non riceve più aggiornamenti dalla directory, come spiega la nota di rilascio.
<?php
/**
* Plugin Name: Vecchioform (versione mantenuta internamente)
* Version: 2.4.1-interno.1
* Requires at least: 6.9
* Requires PHP: 8.1
* Update URI: https://www.example.it/plugin/vecchioform
*/
Le correzioni tipiche riguardano le funzioni rimosse, i parametri null passati alle funzioni interne, le proprietà dinamiche, le query SQL costruite senza $wpdb->prepare() e i controlli di permesso e di nonce mancanti nelle richieste AJAX. Le ultime due sono le cause più comuni delle vulnerabilità nei plugin, e vanno cercate anche se il plugin non dà errori.
Seconda strada: sostituirlo
Se esiste un plugin mantenuto che fa la stessa cosa, sostituire è spesso la scelta più economica nel tempo: la manutenzione la fa qualcun altro. Il costo sta tutto nella migrazione, e va valutato con la scheda preparata prima.
- verificare che l’alternativa copra tutte le funzioni usate, non solo quelle principali;
- controllare che sia compatibile con PHP 8 e con la versione corrente di WordPress, e che venga aggiornata con regolarità;
- trasferire i dati: alcuni plugin offrono un importatore, altrimenti serve uno script che legga le tabelle o i metadati del vecchio plugin;
- sostituire shortcode e blocchi nei contenuti, con
wp search-replaceo con uno script, e aggiornare i template del tema che chiamano le vecchie funzioni; - predisporre i reindirizzamenti se cambiano gli indirizzi delle pagine generate dal plugin;
- rimuovere il vecchio plugin, i suoi file e, dopo una verifica, le sue tabelle e opzioni.
Un plugin di moduli o di gallerie si sostituisce di solito in poche ore. Un plugin che gestisce dati di business, come prenotazioni, iscrizioni o listini, richiede più attenzione, perché i dati storici devono restare consultabili.
Terza strada: riscriverlo
Molti plugin installati per una sola funzione portano con sé decine di file per funzioni che il sito non usa. Quando la funzione è specifica, per esempio l’invio degli ordini a un gestionale o un calcolo particolare in un modulo, scrivere un piccolo plugin su misura che faccia solo quello è spesso più semplice che adattare il codice esistente. Il plugin nuovo nasce già per PHP 8, usa le API attuali di WordPress e contiene solo il codice che serve, quindi ha meno superficie di attacco.
La riscrittura conviene meno quando la funzione è ampia o quando esiste un’alternativa mantenuta. In quei casi si finisce per ricostruire da zero un prodotto, con i costi e i difetti di una prima versione.
Come decidere
La scelta si riduce a poche domande, nell’ordine in cui le poniamo nelle analisi: il plugin serve ancora? Esiste un’alternativa mantenuta che copre le funzioni usate? Il codice è contenuto e leggibile? La funzione è specifica del vostro sito?
| Strada | Quando conviene | Costo nel tempo |
|---|---|---|
| Rimuovere | il plugin non è più usato o la funzione non serve | nessuno, dopo la pulizia dei dati |
| Sostituire | esiste un’alternativa mantenuta e completa | basso: la manutenzione la fa il nuovo autore |
| Adattare | codice contenuto, dati importanti, nessuna alternativa | medio: il codice diventa vostro |
| Riscrivere | funzione specifica, plugin grande per quello che serve | medio: codice piccolo e moderno, ma da mantenere |
In una migrazione a PHP 8 la decisione si prende plugin per plugin, e di solito le strade si mescolano: alcuni plugin si rimuovono, la maggior parte si aggiorna o si sostituisce, uno o due si adattano o si riscrivono. Se il problema riguarda un negozio online, valgono le stesse regole per le estensioni di WooCommerce, con l’attenzione in più per i gateway di pagamento e per l’archiviazione degli ordini, che trattiamo nell’articolo su WooCommerce, PHP 8 e HPOS. Per una valutazione dei plugin del tuo sito trovi come lavoriamo nella sezione sulla migrazione applicativa.
Possiamo dunque riassumere
Un plugin abbandonato si riconosce dall’insieme dei segnali: chiusura nella directory ufficiale, avviso di plugin non testato con le ultime tre versioni di WordPress, nessun rilascio da anni, produttore scomparso, requisiti fermi a versioni fuori supporto. È un rischio anche quando funziona, perché le vulnerabilità restano aperte e il codice blocca il passaggio a PHP 8. Prima di scegliere bisogna sapere cosa fa, dove è usato e quali dati salva, e WP-CLI lo dice in pochi minuti. Poi le strade sono quattro: rimuoverlo se non serve, sostituirlo se esiste un’alternativa mantenuta, adattarlo se il codice è contenuto e i dati sono importanti, riscriverne solo la parte utile se la funzione è specifica. Un plugin adattato o riscritto diventa codice vostro: va mantenuto e protetto dagli aggiornamenti indesiderati con l’intestazione Update URI.