PHP Brought Halloween Forward
Halloween is nine days away and PHP couldn’t wait. On 21 October the PHP project rushed out emergency releases for two unauthenticated remote code execution bugs, a full day ahead of schedule, because the CVE IDs had leaked and half the internet already knew something was coming.
Researchers are calling it PHP2Shell, which sounds like the knock-off version of React2Shell. It’s CVE-2026-109618 and CVE-2026-109619, both rated 9.2, and according to the advisory on php.net every PHP install serving web requests is at risk. FPM, mod_php, php-cgi, FrankenPHP, LiteSpeed, the lot. On Apache with mod_php there’s a working exploit that gets in before a single line of your code has even woken up.
The PHP haters have been waiting for this since 2012. Somewhere, someone who hasn’t touched PHP since mysql_query was in core has dusted off their link to PHP: a fractal of bad design and is typing “I told you so” with both hands. They’re frothing at the mouth like it’s a full moon.
Before anyone gets too excited, go and patch. The fixed versions are 8.5.12, 8.4.27, 8.3.36 and 8.2.35, and the distros got the fixes early, so your package manager probably has them already. If you’re on 8.2, it dies of natural causes on 31 December anyway, so take this as the universe telling you to upgrade.
watchTowr’s honeypots caught people having a go on release day, and Cloudflare says it’s seeing attack traffic, including attempts to sneak past its own protections. Nobody has confirmed a successful break-in yet. In horror movie terms, that’s the bit where the music goes quiet and somebody says “I think it’s gone.”
Can’t patch tonight? The advisory has stopgaps, and these two are the easy ones:
; blocks the confirmed session paths for CVE-2026-109619
session.upload_progress.enabled = 0
; PHP 8.5 only, blocks the fatal backtrace path
fatal_error_backtraces = 0
They go in php.ini or your FPM pool, not ini_set(), and you need to restart every worker. Session upload progress is on by default and the attack doesn’t need your app to call session_start(), so “I don’t use sessions” won’t save you. Think of these as garlic around your neck. They’ll keep the known attacks off you, but the advisory is clear that updating is the only stake through the heart.
The ones I feel for are the undead. According to W3Techs, 69.3% of websites with a known server-side language run PHP. Of those, 27% are on PHP 7 and 7.7% are still on PHP 5, which went end of life at the end of 2018. That’s about a third of all PHP sites on versions that won’t get an official fix.
The PHP team was nice enough to push bare-bones source backports for 7.4, 8.0 and 8.1. PHP 5 gets nothing. And nobody running PHP 7.2 on a shared host they forgot they were paying for is going to compile php-src from a GitHub branch on a weeknight.
The disclosure was a shitshow, and it played out like every slasher film where the group decides to split up. The CVE IDs leaked on 20 October with the wrong severity score attached (10.0, when it’s 9.2). PHP moved the release forward a day. Calif, the security firm whose researcher found the bug, accidentally posted a video of its proof of concept running against several targets, and copies spread on social media. Then Chainguard published container images with the fix more than six hours before the embargo lifted. All that was missing was someone saying “I’ll be right back” and heading down to the basement alone.
The bugs themselves are properly spooky. The first lives in out-of-memory handling. If a request hits memory_limit at just the wrong moment, PHP bails out while its internal request data is half built, and the cleanup code later treats that half-built mess like it’s fine. It’s a zombie. Dead data, shuffling around like nothing happened.
The second one’s a ghost story. A fatal error at the wrong point leaves internal state pointing at memory that belonged to a previous request. That request is dead and its memory has been freed, but the next request on the same worker comes along and uses it anyway. Your new request is being haunted by the last one. I don’t think a bug class has ever lined up with a holiday this well.
All of this lives in C, deep inside the engine, and it’s the same kind of memory bug every runtime written in C or C++ has shipped at some point. CPython is C. Ruby’s interpreter is C. Node is C++ wrapped around V8, which is also C++. A use-after-free doesn’t care what language your controllers are in.
The classic PHP jokes don’t come into it either. Type juggling with ==, haystack and needle swapping places depending on the function’s mood, mysql_real_escape_string, none of it. You could write the most beautiful strictly typed PHP 8.5 anyone’s ever seen and mod_php would still get you, because the exploit lands before your code runs. The call was coming from inside the house.
If you write JavaScript and you’re laughing, I’ve got bad news about your memory. React2Shell (CVE-2025-55182) was disclosed in December 2025 with a perfect 10.0. Unauthenticated RCE in React Server Components, and it was in CISA’s known exploited vulnerabilities list two days later. PHP couldn’t even beat React’s score at its own security disaster. Next.js survived. Everyone patched, and a week later we were all arguing about something else.
The haters do get one point, and the PHP Foundation gift-wrapped it for them. Its post about the release says the first signs of the out-of-memory problem turned up in 2024 during a Quarkslab audit, back when nobody could find a way to exploit it. Then on 11 August this year, Calif and OpenAI each reported a working RCE with the same root cause, independently, which is the security research version of turning up to a party in the same costume.
The foundation’s explanation is that “the delay was a structural failure, caused by both the security team’s decision process and its lack of resources.” Credit to them for saying it out loud. The fix touches memory management and error handling, which you can’t change without risking broken extensions or a slower PHP, and a short-staffed security team stalled while it tried to agree on an approach.
PHP’s getting plenty of attention now, at least. Calif, Wiz, OpenAI, Trail of Bits and Quarkslab have all been poking at it, and Alpha-Omega had it scanned with Claude Mythos earlier this year. The foundation has published 15 CVEs since July and waded through more than 100 bogus, duplicate or non-reproducible reports on top of that. Point that much money and compute at any runtime and see how many skeletons fall out of the closet.
The foundation’s been hiring to keep up, too, and one of the new roles is AI Security Engineer in Residence, a job title that would’ve got you laughed out of a PHP meetup in 2012. It’s still a small group of people looking after the engine under most of the web.
I’ve been writing PHP since the early 2000s, and a couple of nasty CVEs aren’t going to scare me off. If you want to say I told you so to someone, say it to your hosting company. Ask them how much they’ve given the PHP Foundation this year and watch them go as white as a bedsheet with two eyeholes cut in it.
Comments