Skip to main content
October 23, 20268 min read

PHP's New Session Flaw Is Rare, and One Setting Covers It

Get technical support

Patched, monitored, restored on a schedule

CVE-2026-115560 is a rare PHP session flaw with no patch yet. Turning off session upload progress covers it, and many servers already did that this week.

What PHP Announced

Two days after the PHP2Shell releases, the PHP project published an informational advisory on October 23 for CVE-2026-115560. It describes an unlikely remote code execution path in session handling that the October 21 releases, 8.5.12, 8.4.27, 8.3.36 and 8.2.35, do not close. The fix will ship with the next regular bugfix release, together with a full advisory.

Until then PHP suggests one setting, session.upload_progress.enabled=0. It is the same setting the October 21 advisory for CVE-2026-109619 already listed as a mitigation. If you turned it off this week, PHP says to keep it in place, and there is nothing else to do.

The good news is that the conditions are unusual and most applications do not meet them. The setting is also cheap to change, and very few sites use the feature it switches off, so for most teams this is a ten-minute job and not another emergency.

DateWhat happened
October 21PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix CVE-2026-109618 and CVE-2026-109619
October 21The advisory for CVE-2026-109619 lists session.upload_progress.enabled=0 among its mitigations
October 23PHP publishes the informational advisory for CVE-2026-115560, with no patch yet
Next regular bugfix releaseThe fix and the full advisory for CVE-2026-115560

PHP has not yet named the affected versions or given a severity score. When we checked on October 23, the CVE had no record in NVD or on CVE.org, and CISA's catalog of exploited vulnerabilities listed neither this CVE nor the two PHP2Shell flaws.

The Three Conditions

PHP is specific about when the problem can occur. All three of these have to be true at once.

  1. The configuration sets session.serialize_handler to php_binary or php_serialize. That can be in php.ini, an FPM pool, a .user.ini file or the web server configuration.
  2. The application switches the handler to php at runtime with ini_set(), and does so before it calls session_start().
  3. Session upload progress is still enabled.

Remove any one of them and the path is closed. PHP says plainly that applications which never change the serialize handler at runtime can keep upload progress enabled.

Some background on the first two conditions helps. The serialize handler decides the format PHP uses to write $_SESSION to storage and to read it back. PHP's manual lists three formats. php is the default, php_binary is an older internal format, and php_serialize uses the plain serialize() and unserialize() functions. The manual recommends php_serialize for sessions with numeric keys or keys containing | or !, which the older formats cannot store.

The setting can be changed at runtime, which is what condition 2 relies on. An application that configures one format and then switches to another before starting the session ends up reading session data in a different format from the one it was configured to write. PHP has not described the mechanism, and that reading of the conditions is ours, but it explains why the advisory is so narrow.

Why Upload Progress Keeps Coming Up

Session upload progress lets an application show a progress bar for a file upload. When a multipart POST contains a field named after session.upload_progress.name, PHP writes the progress of that upload into $_SESSION, and another request can poll it while the upload runs.

Two details from PHP's own documentation explain why this feature appears in both advisories this week. The progress information is written to the session before any script is executed, so it happens while the request is still starting up and before the application can do anything. The manual also warns that the feature writes the client-supplied file name and field name into the session store, that neither is validated, and that both may contain PHP code. It advises applications that do not use upload progress bars to consider disabling it.

The feature is enabled by default, with session.upload_progress.enabled set to 1, so every PHP installation that has not changed it is running with it on. Very few applications need it, because modern upload interfaces measure progress in the browser instead.

Who Is Likely to Be Affected

Most common stacks do not meet condition 2. Laravel keeps its own session layer and does not use PHP's native session functions, so it never calls session_start(). WordPress core does not use PHP sessions at all, although an individual plugin can. Applications built on Symfony components or on older custom code use native sessions more often, and those are the ones to check.

Shared hosting is the case where the setting matters most. A provider cannot know what code every customer runs, and a single site that changes its serialize handler at runtime is enough. On servers like that, turning upload progress off globally is the safer default, after checking whether any site depends on it.

How to Check Your Code and Configuration

Start with the handler PHP is actually using. The command line and PHP-FPM can read different configuration files, so check the one that serves your sites.

php-fpm8.3 -i | grep -E "session.serialize_handler|session.upload_progress.enabled"
grep -rn "serialize_handler" /etc/php/ 2>/dev/null

If the handler is php everywhere in the configuration, condition 1 is not met and the path is closed for that server. If it is php_binary or php_serialize, look for code that changes it at runtime, and for per-directory settings.

grep -rn --include=*.php "serialize_handler" /var/www | grep -v /vendor/
grep -rln --include=.user.ini --include=.htaccess "serialize_handler" /var/www

Before turning the feature off, check whether anything uses it. The default field name is PHP_SESSION_UPLOAD_PROGRESS, and applications read the progress through upload_progress_ keys in the session.

grep -rln --include=*.php -E "PHP_SESSION_UPLOAD_PROGRESS|upload_progress_" /var/www | grep -v /vendor/

No results means nothing depends on it, and switching it off changes nothing for your users.

How to Turn It Off

Set it where PHP reads it before a request starts, which means php.ini, a configuration drop-in, the FPM pool or the server configuration. PHP's October 21 advisory asks for the setting to be applied administratively and notes that FPM applies .user.ini only after normal initialization, which is later than upload progress runs. An ini_set() call in application code comes later still. Then restart PHP-FPM, or Apache when it runs PHP as a module, because running workers keep the settings they started with.

On Debian and Ubuntu with packaged PHP, a drop-in per version keeps the change separate from php.ini.

echo 'session.upload_progress.enabled = 0' | sudo tee /etc/php/8.3/fpm/conf.d/99-session-upload-progress.ini
sudo systemctl restart php8.3-fpm
php-fpm8.3 -i | grep session.upload_progress.enabled

To stop an individual site from turning it back on, set it in the FPM pool instead with php_admin_flag[session.upload_progress.enabled] = off and restart the pool. On cPanel with EasyApache 4, the drop-in goes into /opt/cpanel/ea-php83/root/etc/php.d/ for each PHP version, followed by /scripts/restartsrv_apache_php_fpm. For the official PHP Docker images, add the line to a file under /usr/local/etc/php/conf.d/ in the Dockerfile and rebuild, since changing a running container does not survive a redeploy.

Servers often carry more than one PHP version. Those built with Forge and similar tools often keep several versions installed side by side, such as 8.1, 8.2 and 8.3, each with its own FPM service and its own configuration directory, and a setting made for one does not reach the others. On Debian and Ubuntu the loop below covers every installed version, and each FPM service that is running then needs its own restart. Only the web-facing SAPIs matter here, since the command line never receives an upload, but writing the file for every version costs nothing and keeps the configuration consistent.

for d in /etc/php/*/fpm/conf.d; do echo 'session.upload_progress.enabled = 0' | sudo tee "$d/99-session-upload-progress.ini" >/dev/null; done
systemctl list-units --no-legend 'php*-fpm.service'

Check the result through the PHP that serves the site, not the command line. The php-fpm -i call above reads the same configuration the FPM workers use.

What the Setting Does Not Cover

The setting is not a substitute for the October 21 update. CVE-2026-109618, the out-of-memory flaw, has nothing to do with sessions, and a server still running a version older than 8.5.12, 8.4.27, 8.3.36 or 8.2.35 stays exposed to it whatever this setting says. Check the version first and the setting second.

The regular release that fixes CVE-2026-115560 will only reach the versions the PHP project still supports. PHP 8.1 and older no longer receive releases, so for them the fix depends on whether a vendor such as Ondrej Sury's PPA or a distribution backports it, as both did for PHP2Shell. Until that happens, on those versions the setting is the only protection, and it is the one place where it may need to stay on the server for good.

What Comes Next

When the next regular bugfix release ships, PHP will publish the full advisory with the affected versions and the fix, and the normal update closes the issue. Leaving upload progress off afterwards is reasonable on any server that does not use it. PHP's October 21 advisory already suggested keeping it off after patching for applications that do not need the feature, and the documentation's own warning about unvalidated file names in the session points the same way.

What We Did This Week

On the servers we patched for PHP2Shell this week, a cPanel host and a custom Ubuntu stack among them, upload progress was switched off as part of that work. CVE-2026-115560 needed no further change there, which is the practical argument for applying the extra mitigations an advisory lists rather than only the version update.

Our earlier posts cover the PHP2Shell fixes in 8.5.12, 8.4.27, 8.3.36 and 8.2.35 and how to prepare for the October 21 release. If you run PHP across several servers and want them checked and kept current, that is part of our servers management work.

Sources

Or read how we handle it in Servers Management.

Related News

Security

The New libssh2 SSH Flaw Is Client-Side, Not Your sshd, and apt upgrade Will Not Fix the Copies That Matter

CVE-2026-55200 is an out-of-bounds write in the libssh2 client library that a malicious or compromised SSH server can use to corrupt a connecting client's memory, and a public proof-of-concept is already out. The corrections that matter: it is client-side and not an OpenSSH or sshd bug, the severity rating is disputed across scorers, and the real cleanup is finding the statically linked and vendored copies a distribution update never touches.

Security

The New cPanel Critical Bug Needs a Valid Login and Still Outscores April's Unauthenticated Root Flaw

CVE-2026-58048, published July 31, 2026, is a 9.4 critical privilege escalation in cPanel and WHM: renaming a database fails to preserve SQL mode, so a customer's SQL executes in root context. It requires a valid cPanel account and the MySQL feature, which sounds reassuring until you compare the scores. April's unauthenticated authentication bypass rated 9.3. This one needs a login and rates 9.4, and the entire difference lives in the CVSS 4.0 subsequent-system metrics: the CNA scored this as breaking out of the account and taking the host with it. On a shared server that means any tenant, including one who paid for a month. Covers the exact first-fixed builds per release tier, the quieter companion CVE, and why automatic updates are the answer to a different question.

Security

PHP Patches Two Unauthenticated RCEs, Worst on mod_php

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix CVE-2026-109618 and CVE-2026-109619, two flaws that allow unauthenticated code execution, worst on mod_php. What changed, who is exposed, and what to do before the update lands.