La mise à jour de PostgreSQL corrigeant 52 CVE est un projet d’upgrade, pas un simple patch. Et PostgreSQL 14, c’est fini

La mise à jour de PostgreSQL corrigeant 52 CVE est un projet d’upgrade, pas un simple patch. Et PostgreSQL 14, c’est fini

Le 12 novembre, le projet PostgreSQL a publié les versions mineures 18.7, 17.12, 16.16, 15.20 et 14.25, ainsi qu’une deuxième release candidate de PostgreSQL 19. Ensemble, elles corrigent 52 CVE et plus de 140 bugs. Pour une version corrective, c’est énorme, et celle-ci demande plus que le traditionnel « on met à jour le paquet, on redémarre, et on rentre chez soi ».

Deux éléments rendent ce cycle différent. PostgreSQL 14.25 est la dernière version de la branche 14 : 14 est donc en fin de vie et ne recevra plus aucun correctif de sécurité ni de bug. Et le correctif du bug principal, CVE-2026-6460, change la façon dont le serveur dialogue avec les extensions. Un patch de routine devient ainsi une mise à jour coordonnée du serveur et des extensions, suivie d’une réindexation et d’une remise à zéro des sauvegardes.

Ce qu’est la CVE-2026-6460

Il s’agit d’une confusion de types qui peut être déclenchée après un ALTER ... SET DATA TYPE. Un utilisateur autorisé à créer des objets peut s’en servir pour exécuter du code arbitraire avec le compte du système d’exploitation sous lequel tourne la base. L’avis officiel lui attribue un score de 8,8 en CVSS 3.1 : exploitable via le réseau, faible complexité, faibles privilèges, aucune interaction utilisateur. Toutes les versions antérieures à 18.7, 17.12, 16.16, 15.20 et 14.25 sont concernées.

« Nécessite des droits de création d’objets » ressemble à une condition rassurante. Je ne pense pas qu’elle le soit. Dans nos missions de pentest, la configuration la plus courante est un rôle applicatif propriétaire de son propre schéma. Les migrations tournent avec ce rôle, l’appli se connecte avec ce rôle, et donc le compte obtenu par une injection SQL peut généralement créer des tables. C’est exactement le profil d’attaquant qu’il faut à cette CVE.

Ce qui me gêne, c’est le rayon d’action. Sur un Postgres auto-hébergé, l’utilisateur système qui fait tourner le serveur peut lire tout le répertoire de données, donc toutes les bases du cluster, pas seulement celle qu’utilise l’appli compromise. Avec Docker, il voit souvent aussi tous les secrets montés dans le conteneur.

Le piège des extensions

Le correctif touche des éléments internes sur lesquels les extensions sont compilées. DatumGetHeapTupleHeader() est passée d’une macro à une vraie fonction du serveur, et heap_getattr() appelle désormais heap_datum_check(). Pour cette raison, les packagers PGDG ont recompilé toutes les extensions contre les nouvelles versions mineures, et leur conseil est de mettre à jour le serveur et ses extensions ensemble.

D’après notre expérience PHP et Docker, voici où cela dérape. Quelqu’un épingle l’image de base Postgres sur un nouveau tag, mais les paquets d’extensions sont installés dans une couche séparée avec leurs propres versions épinglées, ou l’inverse. Mettez à jour les deux dans le même changement, reconstruisez l’image et testez-la avant la production. Si vous compilez vous-même des extensions depuis les sources, recompilez-les avec les nouveaux en-têtes. Une version mineure ne demande normalement pas cela.

Le travail après la mise à jour

L’annonce de la version liste plusieurs corrections qui ne servent qu’une fois certains éléments reconstruits :

  • Les index GIN que vous soupçonnez d’être corrompus doivent être réindexés.
  • Les index GiST pg_trgm créés avec gist_trgm_ops doivent être réindexés.
  • Les index B-tree sur des colonnes bpchar déclarées sans longueur doivent être réindexés.
  • Toute table qui renvoie des erreurs « missing chunk number » nécessite un REINDEX TABLE.
  • Si vous utilisez des sauvegardes incrémentales, faites une nouvelle sauvegarde complète et basez-y toutes les incrémentales suivantes. Plusieurs des bugs corrigés pouvaient produire des incrémentales corrompues.

Pour repérer rapidement les index trigrammes :

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';

Si vous ne faites qu’un point de cette liste, que ce soit la sauvegarde. Une incrémentale corrompue ne donne aucun signe avant le jour où vous restaurez, et c’est le pire moment pour le découvrir. Réindexer de grosses tables consomme du temps et des I/O : planifiez-le sur une plage calme, ne le collez pas simplement à la fin du déploiement du patch.

Mettez aussi à jour les outils clients

Le serveur n’est pas la seule chose à patcher. CVE-2026-116318 est une injection SQL dans pg_dump via les noms de contraintes not-null, et CVE-2026-116330 concerne le script de restauration au format tar, qui ne bloque pas l’injection de commandes psql. L’annonce liste aussi CVE-2026-116314, exécution de code arbitraire dans pg_restore (CVSS 8,8), et CVE-2026-116313, où vacuumdb --missing-stats-only permet à un propriétaire de base d’exécuter du code avec les droits de la personne qui lance vacuumdb (CVSS 7,2). Si quelqu’un d’autre peut créer et nommer des objets dans vos bases, mettez à jour les outils clients en même temps que le serveur.

Pensez aux endroits où ces outils tournent réellement : conteneurs cron de sauvegarde, runners CI, le portable d’ops qu’on utilise pour des restaurations ponctuelles. Quand nous développons des applications cloud-native pour des clients grands comptes, le sidecar de sauvegarde est presque toujours l’image la plus négligée de la stack, épinglée sur la version cliente en vigueur lorsque quelqu’un a écrit le cron. Et il tourne avec des identifiants étendus.

Sur un service managé, vérifiez ce que votre fournisseur a déployé. Même si le serveur est géré pour vous, les outils clients, la réindexation et la chaîne de sauvegarde peuvent rester de votre ressort.

PostgreSQL 14 est terminé

14.25 est le dernier patch de la branche 14. Si vous y êtes encore, appliquez 14.25 maintenant et commencez à planifier la mise à niveau majeure ce trimestre. Ne la repoussez pas à l’an prochain. Pour nos clients grands comptes suisses soumis à des exigences de conformité, une version de base de données non supportée est en soi un constat d’audit, que quelqu’un ait exploité quoi que ce soit ou non.

On voit surtout 14 traîner derrière des applications mobiles. Dans nos projets iOS et Android natifs pour des clients de la santé et de l’IoT, les applis sortent toutes les quelques semaines alors que la base de l’API a été installée une fois, il y a des années, et que personne n’y a touché depuis parce que « ça marche ». Si cela décrit votre backend, voici le coup de pouce qu’il vous faut. Visez 18, la branche stable la plus récente. 19 n’est encore qu’une release candidate et sa place est en préproduction, pas derrière vos utilisateurs. Nous avons mené ces migrations dans le cadre de notre travail de développement, et la mise à niveau de la base elle-même est rarement le plus dur. Le plus dur, c’est de trouver tous les services qui s’y connectent.

Ce que nous ferions cette semaine

  1. Inventorier chaque instance Postgres et sa version, y compris les oubliées en préproduction et en CI.
  2. Mettre à jour ensemble serveur et extensions vers 18.7, 17.12, 16.16, 15.20 ou 14.25.
  3. Mettre à jour pg_dump, pg_restore et vacuumdb partout où ils tournent.
  4. Faire une nouvelle sauvegarde complète si vous utilisez des incrémentales.
  5. Réindexer les index GIN, GiST trigrammes et B-tree bpchar concernés.
  6. Vérifier quels rôles peuvent créer des objets, et retirer ce droit à tout rôle applicatif qui n’en a pas besoin.
  7. Fixer une date au calendrier pour quitter PostgreSQL 14.

Si un cluster PostgreSQL 14 dont personne ne veut se charger vous rappelle quelque chose, parlons-en.

database-securityexpert-analysispostgresqltech-newsupgrade-planning