CVE-2026-109618 und CVE-2026-109619 sind am 21. Oktober 2026 auf php.net erschienen. Beide sind kritisch, beide stecken in der Runtime selbst, und bei beiden kann ein Angreifer Code auf deinem Server ausführen, ohne sich vorher anzumelden. Mein erster Gedanke galt aber gar nicht der Fehlerklasse. Ich hatte all die Slack-Threads vor Augen, die an diesem Morgen um 9:14 Uhr mit „kurze Frage, welches PHP haben wir eigentlich in Prod?“ anfingen und dann unbeantwortet liegen blieben, während jemand den richtigen SSH-Key suchte.

Deshalb mein Standpunkt: Wenn du für die Frage, welche PHP-Version deine Live-Requests verarbeitet, einen Menschen, ein Terminal und eine Vermutung brauchst, dann hast du ein Inventarproblem. Und das nächste Runtime-Advisory wird es aufdecken, ob du bereit bist oder nicht. Jedes Deployment sollte diese Version als Fakt festhalten, direkt neben dem Commit-Hash und dem Composer-Lock. Sie darf nie bloßes Flurwissen sein.

Der Teil mit der Vermutung wiegt schwerer, als die meisten von uns zugeben. Auf ganz normalen Maschinen habe ich schon erlebt, dass `php -v` eine Minor-Version ausgibt, während der FPM-Pool hinter nginx munter eine andere fährt, weil ein Distro-Paket, ein PPA und ein Docker-Base-Image jeweils ihre eigene Meinung dazu hatten. Die CLI ist das, was zufällig als Erstes im PATH liegt. Deine Besucher landen bei dem, worauf die Pool-Konfiguration zeigt. Laufen ein Cronjob, ein Queue-Worker und ein Web-Request auf demselben Host, können das drei verschiedene Interpreter sein, und vielleicht hat nur einer davon den Patch abbekommen.

Der Fix, den ich mir in jeder Codebasis wünsche, ist mit Absicht langweilig. Schreib beim Build `PHP_VERSION` und `PHP_SAPI` in ein kleines Artefakt. Lass zur Laufzeit jede SAPI, die du nutzt, dieselben Werte an einen internen Health-Check melden, und schlag Alarm, sobald die beiden voneinander abweichen oder unter eine Untergrenze fallen, die du in der Konfiguration festlegst. Damit wird der Advisory-Tag zur Dashboard-Abfrage. Du hast in etwa vier Minuten eine Liste der Hosts, um die du dich kümmern musst, statt wie bisher einen Nachmittag lang Archäologie zu betreiben.

Das beste Gegenargument verdient eine ehrliche Antwort: Wer seine exakte Runtime-Version veröffentlicht, liefert einem Angreifer die Aufklärung hübsch verpackt frei Haus. Genau deshalb gibt es `expose_php`, und genau deshalb schalten vernünftige Leute es ab. Da bin ich voll bei dir. Nichts von dem, was ich beschreibe, gehört in einen öffentlichen Header oder auf eine Route ohne Authentifizierung. Die Daten landen in deinem Metrics-Stack oder auf einem tokengeschützten Endpoint, den nur dein Monitoring erreicht. Fingerprinten kann ein Angreifer deinen Stack ohnehin, mit oder ohne deine Hilfe. Wer es nicht kann, bist du, an einem Dienstag, mit einem offenen CVE im Nachbar-Tab.

Dann gibt es noch einen zweiten Einwand: Auf Managed-Plattformen ist die Runtime nicht dein Job. Mag sein, dass es nicht dein Job ist, sie zu patchen, aber das Risiko zu kennen, bleibt deine Sache. Wenn dein Anbieter PHP wirklich aktuell hält, sagt dir das dein Health-Check, und es kostet dich nichts. Wenn nicht, erfährst du es aus deiner eigenen Telemetrie statt aus dem Incident-Report von jemand anderem. Ehrlich gesagt haben es die Go-Leute an dieser Stelle etwas leichter, weil die Runtime direkt in das Binary eingebacken wird, das sie ausliefern. Wir können den Interpreter unter laufendem Code austauschen, und das ist ein echter Vorteil, solange wir im Blick behalten, welcher Interpreter gerade drinsteckt.

PHP hat einen verlässlichen Release- und Security-Rhythmus, und das ist eine der leisen Stärken des Ökosystems. Die Schwachstelle ist die Lücke zwischen einem gefixten Tarball auf php.net und dem Prozess, der tatsächlich auf Port 443 antwortet. Also erzähl mir, wie du diese Lücke schließt. Erfasst dein Team die ausgelieferte PHP-Version heute schon automatisch pro Host, und wenn ja, wo steht diese Zahl: in deinem Deploy-Log, in deinem APM oder immer noch im Kopf von irgendwem?