-FROM php:8.3.35-fpm-bookworm, +FROM php:8.3.36-fpm-bookworm. C'est ce diff d'une ligne que je veux voir dans chaque dépôt PHP cette semaine. Il n'a rien de malin et personne ne lui mettra d'étoile sur GitHub. Mais il transforme un correctif de sécurité critique en pull request avec un pipeline au vert et le nom d'un relecteur dessus, là où tu aurais sinon un fil de mails angoissé avec ton hébergeur et un numéro de ticket que personne ne retrouvera en mars.

Ton interpréteur est une dépendance. C'est même la plus importante de toutes, et la plupart d'entre nous la traitent comme la météo. On épingle 140 paquets Composer sur des hashs de commit exacts, on débat en revue de code d'une montée de version mineure d'une bibliothèque de logs, et ensuite on fait tourner tout ça sur le binaire php qui traînait sur la machine la dernière fois que quelqu'un a lancé apt. PHP2Shell est une bonne raison d'arrêter, et une bien meilleure raison que n'importe quelle conférence sur les builds reproductibles.

Un peu de contexte pour ceux qui ont passé la fin octobre la tête dans le guidon d'un sprint. Le 21 octobre 2026, le projet PHP a publié des correctifs pour CVE-2026-109618 et CVE-2026-109619. Ce sont deux bugs de sécurité mémoire au cœur du moteur. L'un est atteignable via un chemin de manque de mémoire, l'autre est un use-after-free, et à eux deux ils peuvent offrir à un inconnu l'exécution de code sur ton serveur sans même qu'il se connecte. Les versions corrigées sont 8.5.12, 8.4.27, 8.3.36 et 8.2.35. Rien n'existe en amont pour 8.1 ni pour les versions plus anciennes, et 8.2 arrive en fin de vie le 31 décembre 2026 : si tu es en 8.2, tu as un patch à passer maintenant et une migration à planifier avant les fêtes. Le Centre canadien pour la cybersécurité a aussi publié son propre avis, au cas où tes collègues de la conformité auraient besoin d'un deuxième en-tête officiel.

Voilà ce qui rend ce bug inconfortable : aucune de tes alarmes habituelles ne se déclenche. WordPress a publié une note expliquant qu'aucune version du cœur n'est nécessaire pour celui-ci, ce qui est exact, et ce qui veut aussi dire que la bannière jaune de mise à jour dans wp-admin reste muette. Passe Laravel à la dernière version mineure, rien ne change. composer audit revient propre sur un serveur grand ouvert, parce que Composer n'a jamais rien su du binaire qui l'exécute. Ton middleware, tes règles de validation et tes hooks WordPress n'ont pas leur mot à dire quand le moteur est compromis en dessous d'eux. Donc si le runtime n'est pas consigné quelque part où tu regardes vraiment, il est invisible pile au moment où tu en as le plus besoin.

L'objection la plus solide mérite qu'on l'écoute vraiment, et elle a deux volets. D'abord, une énorme part du PHP tourne sur de l'hébergement managé ou mutualisé, et beaucoup de gens l'ont choisi justement pour ne jamais avoir à gérer un binaire. Dire à une agence de cinq personnes qui gère 60 sites WordPress clients de mettre l'interpréteur sous contrôle de version, c'est passer à côté de la raison pour laquelle elle paie un hébergeur. Ensuite, les distributions rétroportent les correctifs sans toucher à la chaîne de version amont, si bien qu'un paquet Debian ou RHEL peut être sûr tout en affichant un numéro qui a l'air vulnérable. S'aligner sur les numéros amont peut te donner de fausses alertes, ou pire, un faux sentiment de sécurité.

Je prends les deux au sérieux, et je ne pense toujours pas que l'une ou l'autre te dédouane. Tu peux déléguer les mises à jour. Tu ne peux pas déléguer le fait de savoir. Même chez un hébergeur où tu n'auras jamais de shell, ton application peut indiquer le runtime qu'elle utilise : un endpoint de santé, une sonde de disponibilité qui lit PHP_VERSION et échoue sous un certain seuil, une ligne dans le log de déploiement. Si les backports brouillent la chaîne de version, consigne plutôt le nom et la release du paquet, mais consigne-les quelque part où tu peux faire un diff. Le but n'est pas un numéro précis. Le but, c'est que la réponse à « qu'est-ce qui tourne ? » soit un fait que tu peux vérifier, pas une supposition. C'est avec les processus de longue durée que les suppositions deviennent dangereuses. Si un master FPM, un worker Octane ou un superviseur Horizon tourne depuis le 19 octobre, il exécute toujours l'ancien code en mémoire, quoi qu'en dise le gestionnaire de paquets.

Nos voisins qui écrivent du Go ont leur runtime compilé dans chaque binaire, qu'ils le veuillent ou non, et ils le paient en recompilant chaque service à chaque changement de toolchain. Nous, on a choisi un interpréteur partagé : moins cher, plus accueillant, et c'est en bonne partie pour ça que PHP fait tourner la moitié du web depuis une offre d'hébergement à dix euros. C'est un vrai avantage. Il vient simplement avec un peu de comptabilité, et PHP2Shell, c'est la semaine où il fallait rendre les comptes.

Alors je pose la question, et j'aimerais vraiment lire tes réponses en commentaires : où vit réellement ta version de PHP en production aujourd'hui ? Dans un Dockerfile, une variable Ansible, un menu déroulant dans un panneau d'hébergement, ou nulle part ? Et si quelqu'un te le demandait cet après-midi, pourrais-tu prouver en dix minutes quel niveau de patch a traité ta dernière requête en production ?