· 7 min read
The PHP bugs, explained with a kitchen
PHP just patched two critical bugs, CVE-2026-109618 and CVE-2026-109619, that let a stranger run their own code on a website's server. Here's what they are in two sentences, what that means if you've never touched PHP, and a restaurant kitchen that explains the rest.
The bugs
On Wednesday, October 21 at 14:00 UTC, PHP shipped fixes for two critical bugs:
- CVE-2026-109618, "RCE via OOM corruption." When a request runs PHP out of memory partway through, PHP abandons it with its internal data half-built, and the cleanup afterwards treats that half-built data as valid.
- CVE-2026-109619, "RCE via stale global state." Data that belongs to one request can survive after its memory has been freed, and the next request handled by the same PHP process can use it before PHP resets it.
Both are rated CVSS 9.2 out of 10. Both are use-after-free bugs: PHP uses memory it has already handed back. Every known way to trigger them is an ordinary file-upload request (multipart/form-data). PHP's advisory says complete remote code execution was "validated over HTTP," and PHP's release notes say "there are no complete mitigations, updating is the only safe choice."
They weren't secret for long. Details leaked the day before, and Cloudflare saw the first attacks at 07:43 UTC on Wednesday, more than six hours before the fix shipped.
What does that even mean?
If that was a lot of jargon, here's the short version: a stranger on the internet could make a website's server run their own code, without logging in, by sending it one carefully built request.
PHP is the language behind a huge share of websites. WordPress runs on it, and so do Laravel, Magento and a lot of the sites you've never thought about. And this bug is in PHP itself, not in any one website. A site with perfectly written code was still exposed.
On Wednesday, a few hours after the patch, someone on X asked for an explanation a six-year-old could follow. This is what I wrote:
php is the kitchen that cooks food for a lot of websites.
— Mr. Nice Try (@MrNiceTry) October 21, 2026
someone found that if you shout a large order, the cook panics.
then stranger can walk in and put something rotten on plate waiting to be served to a customer.
A lot more people read that than anything else I've written about this, so here's the long version.
The kitchen

Think of a website as a restaurant.
- You, the visitor, are a customer. Every time you open a page, you place an order.
- PHP is the kitchen. It takes the order, cooks the page and sends it out on a plate.
- The kitchen has cooks. Each cook takes an order, cooks it, sends it out, and takes the next one. A cook doesn't go home between orders. One cook handles hundreds of orders in a row.
- Each cook has a counter. It's where the ingredients for the current order go. The counter is only so big.
The whole thing works because of one habit: before the next order, the cook wipes the counter. Whatever was there for the last customer gets thrown out, so the next customer's food starts clean.
Both bugs break that habit.
Bug one: shout a large order
Someone walks up to the order window and shouts an order so big it doesn't fit on the counter.
The cook panics. He drops everything, mid-chop, and walks away from the order. That's fine on its own. Kitchens are built for orders that can't be finished.
The problem is what happens next. When the order is abandoned, someone comes by to clean up, and they treat the half-made mess on the counter as if it were a finished dish. Things that were never filled in get handled as if they were.
That's CVE-2026-109618.
Bug two: leftovers on the counter

Sometimes the counter doesn't get wiped. Scraps from the last order, food that was supposed to go in the bin, are still sitting there when the next order comes in. And before the cook gets around to wiping, the next order grabs some of it.
That's CVE-2026-109619. And the panic in bug one is one of the ways to leave a mess behind.
Where the stranger comes in
On its own, a messy counter just means the odd bad plate. Annoying, not dangerous.
But a stranger who understands the kitchen can do more than make a mess. They place the first order to leave exactly the scraps they want on the counter, and a second order to make the cook use them. Now they decide what goes on the plate.
In a kitchen, that's something rotten served to a customer. On a server, it's the stranger's own instructions, carried out with the kitchen's keys: the website's files, its database password, its API keys.
It can also go the other way. Leftovers from someone else's order can end up on the stranger's plate. On a server, that's other visitors' data: passwords, session tokens, keys.
Back to the technical
Here's the same kitchen, with the real names:
| In the kitchen | In PHP |
|---|---|
| The restaurant | A website |
| An order | An HTTP request |
| The kitchen | PHP itself |
| A cook | A PHP worker process (PHP-FPM or Apache's mod_php), which handles request after request |
| The counter | The worker's memory |
| Wiping the counter | PHP resetting its state at the start of each request |
| Shouting a large order | A multipart/form-data request (a file upload) built to cross memory_limit |
| The cook panics | An out-of-memory error: PHP jumps out of the request (longjmp()) halfway through setting it up |
| Treating the mess as a dish | Shutdown treating half-built request data as valid (CVE-2026-109618) |
| Leftovers grabbed by the next order | Global state that points at freed memory, used by the next request before it's reset (CVE-2026-109619) |
| Arranging the scraps | Shaping the heap so the freed memory holds the attacker's data |
| Something rotten on the plate | Remote code execution, as the web server's user |
| Someone else's food on your plate | Memory disclosure |
A few things fall out of that table.
It's the kitchen, not the recipe. Your code is the recipe. These bugs happen while PHP is still reading the request, before WordPress, Laravel or your own code has run a line. Nothing in your app could stop them.
The order window is the way in. Every known trigger is a file-upload request. That's why blocking uploads you don't expect, in front of PHP, helps even when you can't patch yet.
Hiding the whiteboard wasn't enough. Before the patch, the best lead was a feature called session upload progress. Think of it as a whiteboard where the cook notes how much of a big order has arrived. My post on Tuesday night said to switch it off, and PHP's advisory does list it as one place that grabs leftovers. But it isn't the only one: the warnings PHP writes about its own settings, before a request is set up, can grab them too. A PHP core developer warned that turning off upload progress alone isn't enough.
The fix is a cook who always wipes the counter. That's what the patch does: it resets the state properly, every time, whatever happened to the last order. Nothing else does that completely.
What to do

- Update PHP to 8.5.12, 8.4.27, 8.3.36 or 8.2.35: servers, containers, base images, serverless runtimes. If your host manages PHP, ask them whether they have.
- On PHP 8.1 or older, there's no official release. PHP published minimal source backports for 7.4, 8.0 and 8.1, and some Linux distributions and LTS vendors ship their own fixes. Otherwise, move to 8.2 or later.
- Until you can patch, the advisories list partial mitigations: block
multipart/form-datarequests you don't expect at your WAF or proxy, setsession.upload_progress.enabled=0andfatal_error_backtraces=0, and keeppost_max_sizesmall. The Tuesday post has the how-to for php.ini, .htaccess, nginx, Caddy, Cloudflare and WAFs. - Look back at the window before the patch. Uploads to URLs that don't take uploads, bursts of them across many sites, PHP workers crashing, or PHP running
sh,curlorwget. If you find signs someone ran code, treat the server as compromised: rotate every secret it could read, and rebuild it.
Sansec, who track these attacks, say mass exploitation has been less likely than first feared, because the public exploits need specific knowledge of the server. That's a reason to stay calm, not a reason to wait.
On the Edge, the proxy I run in front of a few thousand sites, Tuesday night's rule that blocked the upload progress field is now broader: any multipart request a site doesn't expect gets a 403 before it reaches the kitchen.
The kitchen's open again. Wipe the counter.
I'm @MrNiceTry on X.
Sources: PHP's October 21 security release; the advisories for CVE-2026-109618 and CVE-2026-109619; Sansec on PHP2Shell, including Cloudflare's first sighting at 07:43 UTC.