PHP2Shell: how to check and patch your PHP server
2 flaws in the PHP engine (CVE-2026-109618 and CVE-2026-109619) let anyone run code on a PHP web server without logging in, before the site's own code starts. Which versions fix them, how to check yours in a minute, what the stopgaps close and what they leave open, and what to do on PHP 8.1 or older.
Tecyfy · Published · 7 min read

PHP2Shell is 2 flaws in the PHP engine, CVE-2026-109618 and CVE-2026-109619, that let anyone run code on a PHP web server without logging in. They are fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released on 21 October 2026. If your server runs anything older on those branches, update it today. PHP 8.1 and older get no release from the PHP project at all.
The flaws sit in PHP itself, not in WordPress, Drupal, Magento or Laravel. A site with every plugin patched is still exposed, because the attack runs while PHP reads the incoming request, before the application's first line executes. Exploit write-ups and a tool are public, and attacks were seen before the fixed versions came out.
What goes wrong inside PHP
PHP has an emergency exit. When a request runs out of memory or hits a fatal error, PHP abandons it on the spot and jumps to its error handling, skipping whatever it was in the middle of. Most of the time that is harmless.
PHP2Shell is what happens when the jump lands at the wrong moment. PHP has just set up some internal data for the request, or written down where that data lives, but has not yet finished. The exit frees the memory and leaves the note behind. The next request handled by the same worker process then finds a note pointing at memory that now holds something else, and PHP treats it as its own.
Step through it with 2 requests on one worker:
Request
A
Request
B
One PHP worker
Your code: not started
- A's data
- freed, still pointed at
- B's data
- misread as PHP's own
Request A is a crafted upload. PHP starts reading its body and keeps session data for it, before your application's code runs.
A simplified picture of the 2 bugs' shared pattern (an error exit that skips cleanup, then a later request on the same worker), drawn from the PHP advisory and the researchers' write-ups. The real exploit needs careful timing and memory shaping.
The confirmed way in for the second flaw is session upload progress, a PHP feature that tracks file uploads. It runs while PHP parses a multipart/form-data body, the format browsers use to upload files, so a crafted upload to any PHP address can trigger it, even a page that only prints "OK". On PHP 8.5 there is a second path through the backtrace PHP builds after a fatal error.
Turning this into code execution is hard. The attacker has to land a follow-up request on the same worker and shape the data that fills the freed memory. But the researchers did it against Magento, WordPress, Drupal, Joomla, Nextcloud, Laravel, Symfony and more, with no login. One of the techniques also returns about 67 KB of the worker's memory inside a session cookie, which can include other visitors' sessions and secrets. Code that runs this way has the permissions of the PHP process: not root, but often enough to read the site's configuration, its database password and its API keys.
How to check if your PHP server is vulnerable
Find the version PHP uses for web requests, which is not always the one on the command line:
php -v # the command-line build
php-fpm8.3 -v # the FPM build, with your branch in place of 8.3
curl -sI https://your-site.example | grep -i -E 'x-powered-by|server'
PHP-FPM and Apache's mod_php can be separate packages from the command-line php, so check the one that serves pages. On a managed host or shared hosting, the hosting panel shows the version, and updating it is your provider's job: ask them now.
OpenAI published a free checker, php2shell-checker, as a script and as a Codex skill. node phpcheck.js https://your-site.example reads the version a site announces in its headers, and node phpcheck.js --local reads the local php -v. It answers OK, VULNERABLE or UNKNOWN. Treat UNKNOWN as unpatched: most well-run servers hide the header.
One trap catches careful people. Linux distributions often fix a flaw in their own package without changing PHP's version number, so an older-looking version from your distribution may already carry the fix while the same number built from php.net does not. Check your distribution's security notice for the 2 CVE numbers, not only the version.
Type your version and see which paths stay open:
CVE-2026-109618
A request pushes PHP past its memory limit
Any request that makes PHP run out of memory mid-way.
OpenCVE-2026-109619
Session upload progress (the confirmed path)
Runs while PHP reads the upload, before your code starts.
OpenCVE-2026-109619
Fatal-error backtrace
Only PHP 8.5 has this path.
ClosedCVE-2026-109619
Other variants of the stale state
No setting closes these. Only the fixed release does.
Open
PHP 8.3.30 is affected. Update to 8.3.36. Until then, 3 of 4 known paths stay open.
Paths from the PHP advisory of 21 October 2026 and the researchers' write-ups. A distribution package can carry the fix under an older version number, so a Linux package may be fixed when this says otherwise: check your vendor's notice.
Which PHP versions fix PHP2Shell
The fix is the new PHP release on the server. Nothing in your application code can close it.
- On a supported branch: install 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or your distribution's fixed package, then restart PHP-FPM or Apache so no worker keeps running the old build.
- On the Remi repository: if your RHEL-family server takes PHP from
rpms.remirepo.net, the fix was not there on release day. Switch to your distribution's packages or build from source. - On PHP 8.2: the fix is out, but 8.2 gets no security fixes after 31 December 2026. Plan the move to 8.4 or 8.5 now, while you are in the files anyway.
PHP2Shell workarounds if you cannot update yet
The PHP project lists stopgaps that narrow the attack and says plainly that none makes a server safe. Use them only to buy hours.
session.upload_progress.enabled=0closes the confirmed path for CVE-2026-109619. Set it inphp.inior the FPM pool, never withini_set()or a.user.ini, and restart every worker.memory_limit=-1, set where applications cannot override it, removes PHP's own memory limit as a trigger for CVE-2026-109618. A real allocation failure can still reach the same code, and one request can now take all the server's memory, so watch it.fatal_error_backtraces=0on PHP 8.5 closes the backtrace path.- Reject
multipart/form-dataat nginx or Apache. Every known trigger uses it. It also breaks every file upload and some checkout forms, so test an order after adding it.
Maintenance mode in WordPress or Magento does not help: PHP parses the request before the application checks the flag. If a server matters and cannot be patched, take it offline or serve a static page from the web server.
PHP 8.1, 8.0, 7.4 and older: no official fix
The PHP project no longer releases these branches. You have 3 routes: a backported package from your distribution or an extended-support vendor, the PHP security team's source backports for 7.4, 8.0 and 8.1 if you build PHP yourself, or an upgrade to a supported branch. The vulnerable code goes back to PHP 5.4 from 2012, and the PHP project published nothing for branches older than 7.4. A server on PHP 5 or 7.0 to 7.3 should come off the internet until it is moved.
How AI found PHP2Shell
A researcher at Calif found the first paths on 1 August using GPT-5.6 Sol, OpenAI's model, as part of OpenAI's Patch the Planet programme, and reported them to PHP on 11 August. Wiz found and reported both flaws on its own, 13 days later. PHP's maintainers wrote the fix with partners over 2 months, and distributions got it early. Details leaked on 20 October, and attacks were seen on the morning of 21 October, hours before the fixed versions came out at 14:00 UTC.
That order matters for what you do next. A frontier model found a bug that had sat in PHP since 2012, and the gap between a leak and the first attack was a few hours. When AI finds the bug first follows the 12 weeks from the find to the fix, the attackers running AI agents the same week, and what AI security scanners such as Codex Security and Claude Security do for defenders. Keep a list of every server that runs PHP and who updates it, so the next emergency release takes minutes to apply rather than a day to plan.
Questions
- What is PHP2Shell?
- PHP2Shell is the name for 2 flaws in the PHP engine, CVE-2026-109618 and CVE-2026-109619, both rated 9.2 on CVSS v4.0. When PHP stops a request on an out-of-memory or fatal error, it can leave internal data half-built or pointing at freed memory, and a later request on the same worker can use it. Chained, they let an attacker with no login run code on a PHP web server.
- Which PHP versions fix PHP2Shell?
- PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released on 21 October 2026. PHP 8.1 and older get no release from the PHP project: Linux distributions and LTS vendors may ship backported packages, and the PHP security team published source backports for 7.4, 8.0 and 8.1 for people who build PHP themselves.
- Is WordPress affected by PHP2Shell?
- Yes, if it runs on an unpatched PHP. The flaws are in PHP itself, not in WordPress, so a site with every plugin up to date is still exposed. Researchers ran code without a login on WordPress, Drupal, Joomla, Magento, Nextcloud, Laravel and other PHP apps. The fix is a PHP update on the server, which on managed hosting is your provider's job.
- Does turning off session.upload_progress fix PHP2Shell?
- No. It closes the confirmed path for CVE-2026-109619 once every worker restarts, but not other variants, and it does nothing for CVE-2026-109618. The PHP project says only an update is a complete fix; settings such as session.upload_progress.enabled=0 and memory_limit=-1 only reduce exposure while you get there.
- How do I check if my PHP server is vulnerable to PHP2Shell?
- Find the version PHP runs for web requests, not only on the command line: php -v shows the command-line build, and PHP-FPM can be a different package. Compare it with 8.5.12, 8.4.27, 8.3.36 and 8.2.35 on your branch. OpenAI's free php2shell-checker reads the version a site reveals in its headers, but a hidden header returns UNKNOWN, and a distribution package can be fixed under an older version number.
Sources
Where each fact comes from
- 1Security advisory: Critical remote code execution vulnerabilities, update now
- 2Upcoming Critical PHP Security Release
- 3PHP 8.2.35 Released!
- 4PHP2Shell: Critical PHP RCE (CVE-2026-109618, CVE-2026-109619)
- 5PHP2Shell: When PHP Runs Out of Memory at the Wrong Moment
- 6Frequently Asked Questions About PHP Remote Code Execution (PHP2Shell)
- 7Patch the Planet: global response coordination as agents uncover critical vulnerabilities
- 8php2shell-checker