PHP2Shell Won't Be the Last. Here's Where the Next One Will Show Up First.
October 28, 2026
0 mins readOn October 17, Amazon's honeypot network logged a PHP2Shell exploitation attempt from an anonymized IP address. Yet, public disclosure was still four days away.
By the time PHP got its fixes in on October 21, the technical details had already leaked, proof-of-concept exploits were in wide circulation, and more exploit attempts were being logged left and right. The issue was that there were two critical, unauthenticated remote code execution vulnerabilities in the PHP engine itself (CVE-2026-109618 and CVE-2026-109619, both CVSS v4.0 9.2) -- what we now know as PHP2Shell.
Our own Security Research team covered what happened and what you should do: which releases to move to, which mitigations you could put in place to reduce exposure until you were able to update, and where each part of the Snyk platform sees the problem.
This post now picks up where our Security Research team left off. We want to talk about what the response taught us: where this kind of exposure lives and comes from, why answering fast depends on the work we’d done months earlier, and why the next one is already on its way.
Why was PHP2Shell a problem for teams with clean code?
Well, because the vulnerabilities live below the code. And what does that mean? Both of the mentioned CVEs happen in the request lifecycle of the PHP engine, which makes them reachable before any application code actually runs. On Apache, with mod_php, an exploit needed but a single unauthenticated request.
Now, think about that for a second. You probably had careful reviews, clean code, plus a neat and tidy dependency tree, all sitting above the actual problem. The first question every team faced was where PHP was answering requests, and whether someone could exploit it right then and there.
The question was about running applications. The very same question attackers will always start with.
Which inventory tells you where PHP is running?
Each type of inventory tells you part of it.
PHP reaches production via a Dockerfile, a distribution package, a platform image, or manually. A "php": ">=8.2"constraint in composer.json tells you what an application accepts, and then the deployed version depends on which of those routes installed it. Container scans see PHP installed from distribution packages once each distribution publishes its advisory, and PHP compiled from source, including the official PHP Docker images, falls outside that view. (Once again, our research team's post maps exactly which Snyk view sees which slice of this reality.)
Then there's the version string. VirusTotal fingerprints roughly 5.1 million IP addresses running PHP, and only about 1.1 million of them announce a version, so roughly four out of five hide it. Their summary is one of the cleanest lines we've read on the subject anywhere: "If you only search for a version string, you only see the fraction of the problem that volunteers it."
The gap between what your inside-out views know and what actually answers from the outside is where the real risk lies. Attackers hit your URL, and PHP2Shell is the purest case of that we’ve seen. Anyone probing for it ends up asking the same question: Does PHP answer on this URL?
What did the response look like from the outside in?
The head start: before PHP's 14:00 UTC release on October 21, Snyk had advisories live for both CVEs, so monitored projects would get a hit the moment fixed versions were known. Within about 30 minutes of the release, those advisories included affected ranges and fixed versions, and distribution advisories followed as each distribution was published. That covered what Snyk Container and Unmanaged scans could tell you.
Three questions ran through Snyk API & Web:
Where is PHP running? Discovery enumerates the assets on your domains and fingerprints their technology stack. Set the Tech filter to PHP, and you get every discovered host and endpoint where PHP was identified, with its risk rating, score, and last-seen date. Version numbers come later, from the hosts themselves. As our research team put it, before you can patch, you need the list.
Can someone exploit it? Within 24 hours of PHP's release, the full scan profile tested for PHP2Shell, and teams could run that check on their own as a custom profile for a fast answer across every PHP target.
Did the fix hold? Run the same custom profile after patching, and pair it with your distribution's advisory or patch level, because a patched distribution build can keep an older version number.
So, Discovery --> targeted check --> patch --> re-test: probe, observe, and infer, against a clock that now runs in hours. And that’s exactly the most concerning part, what we care about the most. For teams already running Snyk API & Web, the hard part was done before October 21: their domains were mapped, and their applications set up as targets. When the check was there, the response took only a filter and a quick scan.
For us, that’s one of the main returns on having continuous outside-in testing: the work that answers at day one gets done months before that.
If PHP2Shell is detectable from the outside, what was the hard part?
Time.
In May, we laid out the distinction on which COS is built. Heuristic-detectable vulnerabilities show themselves to deterministic tools: throw payloads at a running application or API, observe the responses, and infer. Context-dependent vulnerabilities (BOLA, cross-tenant leakage, and chained business logic) carry no signature at all, because they live in the gap between what an application is supposed to do and what it actually does.
Once it was known, PHP2Shell became testable from the outside, which puts it squarely in that first class of heuristic-detectable vulns. The hard part, the constraint, was the gap between a disclosure and having a check running against everything you expose. That gap is the attacker’s window to exploit, and this time it opened four days before disclosure eventually did.
The disclosure kept moving, too. On October 23, the PHP project described a partial bypass (CVE-2026-115560) that applies when an application switches its session serialization handler with ini_set() before starting the session, with upload progress enabled. Its preconditions are rare, and whatever you concluded on Wednesday still needed a second look by Friday. A point-in-time answer ages in days.
Why won't PHP2Shell be the last?
There are three reasons for that. Due to the nature of how they were found:
Because they were found with AI assistance, in an engine that has served the web for three decades. Our research team put it plainly: "In a world of LLMs and agents, everybody is still running servers." And the kind of model that found these vulnerabilities is the kind attackers now have in their hands.
The stronger cadence. Manoj Nair, Snyk's CTO and Chief Innovation Officer, described it in September: "The kind of severe flaw that AI now surfaces in widely used software, the sort of find that used to arrive once or twice a year and reset everyone's quarter, is landing several times a week in what I'm seeing."
The much faster clock. CJ Moses, CISO of Amazon Integrated Security, drew two lessons from PHP2Shell that apply well beyond it. Defenders "should not assume the public disclosure date is the earliest date of exploitation." And "the time from patch to working exploit is shrinking for structural reasons," because AI-assisted analysis makes it cheaper to turn a patch diff or an advisory into a working exploit. His advice for critical vulnerabilities in internet-facing systems: "measure patch and mitigation timelines in hours."
What does being ready for the next one take?
Strip out the product names, and it comes down to four properties. Judge any approach by them (ours included). Don’t think about product names, but how it all comes down to four properties. And you should judge any approach with these (ours included!)
An inventory that exists before the advisory does. Built from the outside in and kept current, so a new disclosure starts with a filter.
Checks that ship in hours. The gap between an advisory and a running test is the attacker's window. Measure it.
Re-tests on demand. The same targeted check, run again until the fix holds.
Testing that needs no signature. Heuristics catch what someone has already described. Everything else takes reasoning: testing that works out what your application is supposed to do, then goes after the gap between that and what it actually does.
As for Snyk, here’s how that maps to what we offer.
Snyk API & Web carries the first three: Discovery, an engine the team keeps current as disclosures land, and targeted profiles you can run and re-run. Continuous Offensive Security adds the fourth: AI Pentesting reasons about your application the way a pentester would, Agent Red Teaming engages the moment recon spots an LLM in the stack, and Dynamic Testing, the Snyk API & Web engine, covers the heuristic classes underneath, continuously. In our platform's terms, that's Validate: continuously attack your applications to prove fixes held and show what's still exploitable.
Then there's posture. At The AI Security Panel: Unfiltered on October 14, Manoj asked the question we keep coming back to: "When an autonomous attacker is going to attack you, why don't you attack yourself?" That question is the whole premise of COS. On our side, the work is shrinking every single gap in this story: from advisory to running check, and from check to confirmed fix.
Where will the next one show up first?
Which engine, and when, is anyone's guess now. Where it shows up first is easier to call: at your URL. That's where your testing should already be.
Want to see what an attacker would find at your URL today? Book a demo of Evo Continuous Offensive Security and see how it maps your attack surface from the outside in, proves which findings are exploitable, and re-tests until the fix holds.
BOOK A LIVE DEMO
Secure AI adoption at scale
Evo helps organizations safely adopt and scale AI by providing visibility, governance, and security across AI-driven development and AI applications.



