The Race Between Patches and Exploits

On 20 October 2026 the PHP project gave the world a heads-up: fixes for two critical vulnerabilities would ship the next day. On 21 October they landed. CVE-2026–109618 and CVE-2026–109619, quickly nicknamed php2shell, both scored 9.2 and can lead to unauthenticated remote code execution.

A good part of willhaben Motornetzwerk runs on PHP: the tools our dealer partners use every day, plus the websites we run for them. This is how we handled it, what we found when we went looking afterwards

Why this one was different

Most PHP vulnerabilities live in application code: a bad include, an unsafe unserialize, a missing check. You fix your app and move on.

php2shell vulnerabilities are sitting one layer below. Before your framework boots, before routing, before authentication, PHP parses the raw request: form fields, multipart bodies, upload progress. That’s where the trouble starts:

  • CVE-2026–109618: if PHP runs out of memory at exactly the wrong moment while building its internal structures, it abandons one half-built, then later “cleans it up” as if it were valid. A carefully shaped request can turn that cleanup into code execution
  • CVE-2026–109619: state belonging to one request can outlive its memory, and a later request on the same worker can stumble into it
How these could turn memory handling errors into unauthenticated remote code execution

That’s what made it uncomfortable: none of the usual safety nets apply. Authentication, input validation and framework hardening all run after the point where these bugs can fire. How exposed you are depends on how PHP is deployed. The most direct path was demonstrated on Apache with mod_php. Other setups have narrower, more application-dependent paths. The only things that can stop a request earlier sit in front of PHP: a reverse proxy, an edge WAF, request limits.

The afternoon half the internet went offline

20 October, evening. We received an early warning about a critical undisclosed vulnerability in PHP, with patches expected the next day. There were no public technical details yet, so at that point, the plan was to wait for new information and the patch to deploy it as soon as possible.

21 October, around 12:00. That started to change. Recommendations to take PHP services offline as a precaution were circulating, and we were already seeing some organizations doing exactly that. With the vulnerability still not fully understood and no patch available, simply waiting was becoming harder to justify.

14:40. We opened an incident channel and pulled everyone in at once: engineering, ops, product and customer communications.

14:40–15:20. Triage, while the internet produced a lot of noise.

Within hours there were one-line “fixes” everywhere: disable session.upload_progress, block all multipart uploads at the web server, put a WAF in front. We rolled out the cheap ones as stopgaps.

The PHP team was explicit that no configuration change fixes these bugs. The session setting only blocks the confirmed session-related paths of one of the two CVEs, while blocking multipart requests reduces the attack surface but does not cover every possible way to trigger these vulnerabilities.

15:20–15:45. The decision

We had a pre-auth RCE rated 9.2 affecting systems our partners depend on, no patch available yet, and workarounds we could not fully trust. So we made the call to take these services offline and put them into maintenance mode. Given the uncertainty and the warnings from the PHP community, we preferred a few hours of planned downtime over a “let’s see what happens” approach.

We weren’t alone. That afternoon, organisations across Austria and beyond took PHP services offline as a precaution, from university portals to news sites. Precautionary shutdowns aren’t new; plenty of teams did the same for previous critical exploits in the years before. But even for something as widely used as PHP, this wave felt unusually broad. A major factor was likely the risk that a published fix also gives attackers a map: anyone can inspect the patched code and see exactly where the bug was. With today’s automation and AI tooling, the gap between “patch published” and “a working exploit being attempted in swarms” keeps shrinking. Looking at that gap and we decided not to stand in it.

Shortly after 15:30. PHP published 8.2.35, 8.3.36, 8.4.27 and 8.5.12

16:27–16:57. The websites came back first, patched as soon as fixed packages were available. The temporary multipart block came off again.

~17:00–18:59. Here’s a detail that’s easy to miss. The fixed PHP release was out quickly, but the official container images followed hours later. Any team waiting for the official image stayed exposed for that whole time or would have to wait until the next day.

We instead built a patched image, ran it through our checks and deployed it.

18:59. Dealer tools back online on the patched version, after about three hours and twenty minutes offline.

By 19:02 the maintenance banners were gone.

Then we went looking

Being patched answers “are we safe now?”. It doesn’t answer “did anything happen before?”. Amazon reported php2shell attempts on its honeypots as early as 17 October, four days before disclosure, so we didn’t limit our review to the hours after the patch. We also went back through the days before it.

On the websites, our review of the available logs and systems did not identify indications of compromise, such as webshells, unexpected processes or unauthorised admin accounts.

On the dealer platform, the logs showed a clear change in traffic. In the month before disclosure, we did not observe oversized POST requests of the kind php2shell relies on. Just a few hours after we came back online, we counted dozens of them coming from multiple sources:

  • an automated scanner using methods associated with php2shell exploitation
  • bursts of oversized POST requests aimed at PHP’s request parser, sent from cloud servers in scripted waves;
  • sprays of large requests across the default login pages of common PHP applications. Copy-paste recipes, fired at everything.

According to our deployment records, these requests only started appearing after the patched version was live. Where they reached PHP, our logs indicate they were cut off early. In the logs we reviewed, we did not find memory exhaustion, fatal errors, crashed workers or server errors linked to them. A second, independent log source at the network edge was consistent with this for the time windows we checked.

Logs have limits, and a well-built exploit doesn’t necessarily crash anything or need an unusually large request. What we can say is that the noisy probing we saw after the patch did not show up in our logs before it. Based on the information available to us, we have not identified indications of successful exploitation, and we keep monitoring.

About those proofs of concepts

We also tested a few public proofs-of-concept released after the patch against an unpatched copy of our own setup. Outside the lab environments they shipped with, they did not work for us. That lines up with what researchers have written since: these exploits are tied to specific PHP builds and configurations and have to be adapted to each target, and many of the scripts that circulated in the first hours never worked at all. A public PoC is not ground truth.

And none of this was a reason to relax. Configuration adds friction, not safety. A setup that breaks the public recipes still has the bug; it may just take more effort to hit, and some settings can even make the underlying bug easier to trigger. The PHP advisory points that way for memory limits in particular. A determined attacker with time and a specific target can work around friction. Only the patch removes the bug.

And on the afternoon of 21 October, none of this was clear yet. Nobody, outside the group that reported these vulnerabilities, fully understood how exploitable the bugs were or what a real attack would look like. We did not weigh our system against the risk, simply because we could not.

So we took the precautionary route and only checked afterwards whether we had even been safe before this issue became public.

What we’d tell

With AI agents digging through public repositories like PHP, we will certainly see more critical vulnerabilities in software. But the bigger concern is not just how many vulnerabilities get discovered, it is how quickly they become dangerous.

A published patch fixes the vulnerability, but also shows everyone where to look. We saw that ourselves. Within hours of the patch becoming public, attempts were already hitting our systems that we had not seen before. They were not good attempts, and they arrived too late, but they came remarkably fast.

With agentic tooling, the gap between a published fix and an exploit spreading in swarms that is adapted to a specific system can shrink even further. What once required time, expertise and manual effort can increasingly happen at scale.

That leaves less and less time to figure out whether something really affects us.

What stood out this time was how many organisations, not just us, were willing to take systems offline as a precaution. Taking systems offline over security concerns is nothing new, and PHP is widely used across the web. But seeing it happen on this scale showed just how seriously the risk was being taken.

It is also a reminder that teams need to be prepared to make the same decision in the future


The Race Between Patches and Exploits was originally published in willhaben Tech Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.