-FROM php:8.3.35-fpm-bookworm, +FROM php:8.3.36-fpm-bookworm. I want to see that one-line diff in every PHP repository this week. It isn't clever and nobody will star it on GitHub. What it does is turn a critical security fix into a pull request with a green pipeline and a reviewer's name attached, where otherwise you get an anxious email thread with a hosting provider and a ticket number nobody can find again in March.
Your interpreter is a dependency. It is the most important dependency you have, and most of us treat it like the weather. We pin 140 Composer packages to exact commit hashes, argue in code review about a minor bump to a logging library, and then run all of it on whatever php binary happened to be on the box when someone last ran apt. PHP2Shell is a good reason to stop doing that, and it's a better reason than any conference talk on reproducible builds.
Some quick context for anyone who spent late October heads down in a sprint. On October 21, 2026 the PHP project released fixes for CVE-2026-109618 and CVE-2026-109619. Both are memory-safety bugs deep in the engine. One is reachable through an out-of-memory path and the other is a use-after-free, and together they can give a stranger code execution on your server without logging in. Patched builds are 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Nothing upstream exists for 8.1 or anything older, and 8.2 hits end of life on December 31, 2026, so if you're on 8.2 you get a patch now and a migration to plan before the holidays. The Canadian Centre for Cyber Security put out its own advisory too, in case your compliance people need a second letterhead.
This is what makes the bug uncomfortable: none of your usual alarms go off. WordPress published a notice saying no core release is needed for this one, which is accurate and also means the yellow update banner in wp-admin stays quiet. Bump Laravel to the latest minor and nothing changes. composer audit comes back clean on a server that is wide open, because Composer has never known anything about the binary running it. Your middleware, validation rules and WordPress hooks don't get a say when the engine is compromised underneath them. So if the runtime isn't recorded somewhere you actually look, it's invisible right when you need it most.
The strongest objection deserves a proper hearing, and it comes in two parts. First, a huge share of PHP runs on managed or shared hosting, and plenty of people chose that so they would never have to own a binary. Telling a five-person agency running 60 client WordPress sites to put the interpreter in version control misses the reason they're paying a host. Second, distributions backport fixes and leave the upstream version string alone, so a Debian or RHEL package can be safe while reporting a number that looks vulnerable. Pinning to upstream numbers can give you false alarms, or worse, false comfort.
I take both seriously, and I still don't think either one gets you off the hook. You can hand off the patching. You can't hand off knowing. Even on a host you'll never get a shell on, your application can report the runtime it's using: a health endpoint, an uptime check that reads PHP_VERSION and fails below a threshold, a line in the deploy log. If backports are muddying the version string, record the package name and release instead, but record it somewhere you can diff. The goal isn't a particular number. The goal is that the answer to "what's running?" is a fact you can look up instead of a guess. Long-lived processes are where the guessing gets dangerous. If an FPM master, an Octane worker or a Horizon supervisor has been up since October 19, it's still running the old code in memory, whatever the package manager says.
Our Go-writing neighbours get their runtime compiled into every binary whether they want it or not, and they pay for that by rebuilding every service whenever the toolchain changes. We picked a shared interpreter, which is cheaper, friendlier and a big part of why PHP runs half the web from a ten-euro hosting plan. That's a real advantage. It just comes with a bit of bookkeeping, and PHP2Shell is the week that bookkeeping was due.
So I'll ask, and I'd really like the answers in the comments: where does your production PHP version actually live right now? A Dockerfile, an Ansible variable, a dropdown in a hosting panel, or nowhere at all? And if somebody asked you this afternoon, could you prove within ten minutes which patch level handled your last production request?




Comments
No comments yet — be the first.
Open the discussion
No account or password needed — just enter your e-mail and we’ll send you a one-time sign-in link. First time here? You’re set up automatically.
Your rating will be applied automatically after you sign in.
Check your inbox
We’ve sent a sign-in link to …. Open it on this device — this tab will sign you in automatically.
Nothing arrived? Check your spam folder — and mark the mail as "Not spam" so it lands in your inbox next time.