L'aggiornamento PostgreSQL con 52 CVE è un progetto di upgrade, non una patch. E PostgreSQL 14 è finito

L'aggiornamento PostgreSQL con 52 CVE è un progetto di upgrade, non una patch. E PostgreSQL 14 è finito

Il 12 novembre il progetto PostgreSQL ha rilasciato le minor release 18.7, 17.12, 16.16, 15.20 e 14.25, più una seconda release candidate di PostgreSQL 19. Complessivamente chiudono 52 CVE e correggono più di 140 bug. Per una point release è un numero enorme, e stavolta serve più del solito «aggiorna il pacchetto, riavvia e vai a casa».

Due elementi rendono questo giro diverso. PostgreSQL 14.25 è l'ultima release del ramo 14, che quindi è a fine vita (end-of-life) e non riceverà altre correzioni di sicurezza o di bug. Inoltre la correzione del bug principale, CVE-2026-6460, cambia il modo in cui il server dialoga con le estensioni. Così una patch di routine diventa un aggiornamento coordinato di server ed estensioni, seguito da qualche reindicizzazione e dal reset dei backup.

Che cos'è CVE-2026-6460

È una type confusion che può essere innescata dopo ALTER ... SET DATA TYPE. Un utente autorizzato a creare oggetti può sfruttarla per eseguire codice arbitrario come l'account del sistema operativo con cui gira il database. L'advisory ufficiale le assegna 8,8 su CVSS 3.1: raggiungibile via rete, bassa complessità, privilegi bassi, nessuna interazione dell'utente. Sono interessate tutte le versioni precedenti a 18.7, 17.12, 16.16, 15.20 e 14.25.

«Servono privilegi di creazione oggetti» sembra una precondizione rassicurante. Secondo me non lo è. Nei nostri penetration test la configurazione più comune che troviamo è un ruolo applicativo proprietario del proprio schema. Le migrazioni girano con quel ruolo, l'app si connette con quel ruolo e quindi l'account in cui finisce una SQL injection di solito può creare tabelle. È esattamente il profilo di attaccante che serve a questa CVE.

A preoccuparmi è il raggio d'azione. Su un Postgres self-hosted, l'utente del sistema operativo che esegue il server può leggere l'intera directory dei dati, cioè ogni database del cluster, non solo quello usato dall'app compromessa. Negli ambienti Docker spesso vede anche tutti i secret montati nel container.

Il problema delle estensioni

La correzione tocca parti interne rispetto alle quali le estensioni vengono compilate. DatumGetHeapTupleHeader() è passata da macro a vera funzione del server e heap_getattr() ora chiama heap_datum_check(). Per questo i packager di PGDG hanno ricompilato ogni estensione rispetto alle nuove minor release, e consigliano di aggiornare insieme server ed estensioni.

Per la nostra esperienza con PHP e Docker, ecco dove si sbaglia. Qualcuno fissa l'immagine base di Postgres a un nuovo tag, ma i pacchetti delle estensioni sono installati in un layer separato con versioni fissate a parte, o viceversa. Aggiornate entrambi nella stessa modifica, ricostruite l'immagine e testatela prima che arrivi in produzione. Se compilate voi stessi le estensioni dai sorgenti, ricompilatele con i nuovi header. Di norma una minor release non lo richiede.

Il lavoro dopo l'upgrade

L'annuncio della release elenca diverse correzioni che servono solo dopo aver ricostruito alcune strutture:

  • Gli indici GIN che sospettate corrotti vanno reindicizzati.
  • Gli indici GiST di pg_trgm creati con gist_trgm_ops vanno reindicizzati.
  • Gli indici B-tree su colonne bpchar dichiarate senza lunghezza vanno reindicizzati.
  • Ogni tabella che genera errori «missing chunk number» richiede REINDEX TABLE.
  • Se usate backup incrementali, eseguite un nuovo backup completo e basate su di esso tutti gli incrementali successivi. Diversi bug corretti potevano produrre incrementali corrotti.

Per trovare rapidamente gli indici trigram:

SELECT i.indexrelid::regclass AS index_name
FROM pg_index i
JOIN pg_opclass o ON o.oid = ANY (i.indclass::oid[])
WHERE o.opcname = 'gist_trgm_ops';

Se fate una sola cosa di quell'elenco, fate il backup. Un incrementale corrotto non dà alcun segnale finché non ci si ripristina, e quello è il momento peggiore per scoprirlo. Reindicizzare tabelle grandi richiede tempo e I/O, quindi pianificatelo in una finestra tranquilla. Non aggiungetelo semplicemente in coda alla patch.

Aggiornate anche i client

Il server non è l'unica cosa da patchare. CVE-2026-116318 è una SQL injection in pg_dump tramite i nomi dei vincoli not-null, mentre CVE-2026-116330 riguarda lo script di ripristino in formato tar, che non blocca la command injection di psql. L'annuncio elenca anche CVE-2026-116314, esecuzione di codice arbitrario in pg_restore (CVSS 8,8), e CVE-2026-116313, per cui vacuumdb --missing-stats-only permette al proprietario di un database di eseguire codice come chi lancia vacuumdb (CVSS 7,2). Se qualcun altro può creare e nominare oggetti nei vostri database, aggiornate i client insieme al server.

Pensate a dove girano davvero questi strumenti: container cron per i backup, runner CI, il laptop di chi fa ripristini ad hoc. Quando sviluppiamo app cloud-native per clienti enterprise, il sidecar di backup è quasi sempre l'immagine più trascurata dello stack, bloccata alla versione client in uso quando qualcuno scrisse il job cron. E gira anche con credenziali ampie.

Su un servizio gestito, verificate cosa ha rilasciato il vostro provider. Anche se il server è gestito per voi, strumenti client, reindicizzazione e catena di backup potrebbero restare a vostro carico.

PostgreSQL 14 è finito

14.25 è l'ultima patch che il ramo 14 riceverà. Se siete ancora su questa versione, applicate subito 14.25 e iniziate a pianificare l'upgrade maggiore in questo trimestre. Non rimandatelo all'anno prossimo. Per i nostri clienti enterprise svizzeri con requisiti di compliance, una versione di database non supportata è già di per sé un rilievo di audit, indipendentemente dal fatto che qualcuno abbia sfruttato qualcosa.

Vediamo la 14 sopravvivere soprattutto dietro le app mobile. Nei nostri progetti nativi iOS e Android per clienti del settore sanitario e IoT, le app escono ogni poche settimane mentre il database dell'API è stato configurato una volta, anni fa, e nessuno lo ha più toccato perché «funziona e basta». Se il vostro backend è così, questo è lo stimolo giusto. Puntate alla 18, il ramo stabile più recente. La 19 è ancora una release candidate e va in staging, non davanti ai vostri utenti. Abbiamo fatto queste migrazioni nell'ambito del nostro lavoro di sviluppo e l'upgrade del database in sé raramente è la parte difficile. Lo è trovare tutti i servizi che vi si connettono.

Cosa faremmo questa settimana

  1. Fate l'inventario di ogni istanza Postgres e della sua versione, comprese quelle dimenticate in staging e nella CI.
  2. Aggiornate insieme server ed estensioni a 18.7, 17.12, 16.16, 15.20 o 14.25.
  3. Aggiornate pg_dump, pg_restore e vacuumdb ovunque girino.
  4. Eseguite un nuovo backup completo se usate incrementali.
  5. Reindicizzate gli indici GIN, GiST trigram e B-tree su bpchar interessati.
  6. Controllate quali ruoli possono creare oggetti e togliete subito questo diritto ai ruoli applicativi che non ne hanno bisogno.
  7. Fissate in calendario una data per lasciare PostgreSQL 14.

Se un cluster PostgreSQL 14 che nessuno vuole gestire vi suona familiare, parliamone.

database-securityexpert-analysispostgresqltech-newsupgrade-planning