CVE-2026-115560: The PHP RCE the PHP2Shell Patch Doesn't Fix — Check in 2 Minutes
PHP's October 23 advisory: CVE-2026-115560, an RCE path via session upload progress not fixed in 8.5.12/8.4.27/8.3.36/8.2.35. Who is exposed, the one-line mitigation, and a free check script.
Published by Zero Hunt, an autonomous AI red team on an on-premise appliance running private AI: automated penetration testing for networks and infrastructure, black-box or gray-box, with a human approving every step that matters.
Two days after the emergency PHP2Shell releases, the PHP project published a second notice. On October 23, 2026 it issued an "informational advisory" for CVE-2026-115560, a remote code execution path through session upload progress that the October 21 releases (8.5.12, 8.4.27, 8.3.36, 8.2.35) do not fix. PHP's advice: set session.upload_progress.enabled=0 until the next regular bugfix release.
PHP calls the vector "unlikely": it needs an unusual combination of configuration and application code. That is good news, but not a reason to skip it. The mitigation is a one-line change that most sites will never notice, and the PHP2Shell attacks seen since October 21 already abuse the same upload-progress feature (for CVE-2026-109619). Below: who is exposed, how to check a host in two minutes with a free script, and how to apply the mitigation on each platform.
At a glance
- What: CVE-2026-115560, remote code execution via session upload progress. Announced by PHP on October 23, 2026 as an informational advisory; the full advisory will come with the next release.
- Fixed in: no release yet. Updating to 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 is still mandatory for PHP2Shell, but does not close this path.
- Exposed only if all three hold: the configuration sets
session.serialize_handlertophp_binaryorphp_serialize; the application switches it tophpwithini_set()beforesession_start();session.upload_progress.enabledis still on (it is on by default). - Mitigation:
session.upload_progress.enabled=0. If you applied it after the October 21 advisory for CVE-2026-109619, keep it: no further action is needed. - Severity, affected versions, exploitation: PHP has not published a score or a version list. We found no report of exploitation of CVE-2026-115560 as of October 24; the attacks seen since October 21 target the two PHP2Shell CVEs.
- Free check:
php2shell-check.sh0.2.0 checks the three conditions on your host. Read-only, runs on your machine, nothing leaves your network.
What PHP announced
The PHP news item of October 23 says, in full substance:
We suggest you set session.upload_progress.enabled=0 until the next regular bugfix release, to fully protect from an unlikely RCE vector. [...] The issue can only occur under an unusual combination of configuration and application code. An application must set session.serialize_handler to php_binary or php_serialize in its configuration and then switch it to php at runtime with ini_set() before calling session_start(). Session upload progress must also still be enabled. Applications that never change the serialize handler at runtime can keep the feature enabled.
PHP is handling it in the regular release cycle, not as an emergency, and will publish the full advisory for CVE-2026-115560 with that release.
The same setting was already one of the stopgaps in the October 21 advisory GHSA-6wmf-4rv5-p3rp for CVE-2026-109619. There, PHP describes session upload progress as a confirmed "consumer" of stale state: it "can reach session handling before ordinary session initialization", it is enabled by default, and it needs no session_start() call from the application. The new CVE is a separate route through the same feature, and it survives the patch.
Who is exposed
The three conditions narrow it a lot:
- The serialize handler is changed in configuration. The default is
php. You are only in scope ifphp.ini, aconf.dfile, an FPM pool, an Apachephp_value,.htaccessor.user.inisetssession.serialize_handlertophp_binaryorphp_serialize. - The application switches it back to
phpat runtime. Something callsini_set('session.serialize_handler', 'php')beforesession_start(). This can sit in your code or in a library undervendor/. - Session upload progress is on. It is on by default in every supported branch, so most hosts meet this condition unless someone already turned it off for PHP2Shell.
If your servers never touch session.serialize_handler, PHP says you can keep the feature. In practice most teams will turn it off anyway: it is one line, and few applications rely on the upload progress data in $_SESSION (modern upload bars usually track progress in the browser).
Check a host in two minutes
Our free script now checks the three conditions, alongside the PHP2Shell checks it already ran:
curl -fsSLO https://zerohunt.ai/self-check/php2shell-check.sh
sha256sum php2shell-check.sh # compare with https://zerohunt.ai/self-check/SHA256SUMS
less php2shell-check.sh # read it first
sudo sh php2shell-check.sh --scan /var/www/myapp # your web root(s); default: /var/www /srv/www /usr/share/nginx
In the CVE-2026-115560 section it reports, for each web php.ini (FPM, Apache, CGI, LiteSpeed, cPanel, Plesk, Remi, Docker) and each FPM pool, the effective session.upload_progress.enabled and session.serialize_handler, then lists any PHP, .htaccess or .user.ini file under your web roots that sets the serialize handler. The verdict:
[ok ]upload progress is off everywhere it is set: the mitigation is in place;[ok ]upload progress is on but nothing switches the handler at runtime: the conditions are not met;[CHECK]some code sets the serialize handler: read those files;[FIX ]the config usesphp_binary/php_serializeand code sets the handler: turn upload progress off now.
The script only reads files and versions. It changes nothing, opens no network connection and sends nothing anywhere. Source and tests: github.com/ZeroHunt-org/self-check.
Prefer to check by hand? Two commands cover it:
grep -rnE 'session\.(serialize_handler|upload_progress\.enabled)' /etc/php* /usr/local/etc/php* 2>/dev/null
grep -rn 'serialize_handler' --include='*.php' --include='.htaccess' --include='.user.ini' /var/www
Remember that the CLI reads a different php.ini from the web server: php -i on the command line does not tell you what PHP-FPM or mod_php uses.
Remediation
Set session.upload_progress.enabled to off where the web PHP reads it, then restart PHP so every worker picks it up.
- php.ini or a conf.d file (Debian/Ubuntu:
/etc/php/<version>/fpm/conf.d/and/etc/php/<version>/apache2/conf.d/; RHEL family:/etc/php.d/):; CVE-2026-115560 mitigation, until the next PHP bugfix release session.upload_progress.enabled = 0 - PHP-FPM pool, so applications can't turn it back on:
php_admin_flag[session.upload_progress.enabled] = off - Apache with mod_php, in the server or vhost configuration:
php_admin_flag session.upload_progress.enabled off - Official Docker
phpimages: add the line to a file in/usr/local/etc/php/conf.d/, rebuild and redeploy the image. - Shared hosting: some providers have already disabled the feature for every customer; check your provider's notice.
Then restart: systemctl restart php8.3-fpm (your version), systemctl reload apache2 or httpd. Verify with php-fpm8.3 -i | grep upload_progress or by running the check script again.
Keep the setting until the PHP release that fixes CVE-2026-115560 is out and installed. And do not treat it as a PHP2Shell fix: CVE-2026-109618 and CVE-2026-109619 still need the update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, as explained in our PHP2Shell remediation guide.
What is not known yet
- The severity score and the exact affected versions: PHP will publish them with the full advisory.
- The release date of the fix, other than "the next regular bugfix release".
- Whether any widely used framework or CMS switches the serialize handler at runtime. We found no public report naming one.
One host is not the whole estate
A script tells you about the host you run it on, today. The harder question during a week like this is where PHP runs that nobody remembers: a forgotten admin panel, a vendor appliance, a container image built last year. Zero Hunt is an autonomous AI red team on an on-premise appliance, with its own private models and a human approval gate for every action that matters. It maps the exposed services across your network, checks which ones a real attack path can reach, and re-tests after you patch to prove the fix held. Nothing leaves your network. Our team can walk you through it, and the free self-check scripts stay free.
Every vulnerability CISA lists as exploited, with federal due dates: CISA KEV tracker →
Patching one CVE at a time? A CTEM program validates which exposures are actually exploitable before the next advisory: what CTEM is →
Is this exploitable in your environment?
Zero Hunt answers that on your own network: an autonomous AI red team on an on-premise appliance, running on private AI, black-box or gray-box, with a human approving every step that matters. Proof of what is exploitable, the fix, and signed evidence — no data leaves your perimeter.