Current situation: PHP2Shell. Two critical PHP vulnerabilities (CVSS 9.2) allow malicious code without login. Patches since 21 October 2026.What to do now →

Disabling session.upload_progress: Correctly and Permanently

The remedy for CVE-2026-115560 and one of the PHP2Shell interim measures is quickly set. For it to hold, it must be in the right place, locked and rechecked after every update.

Last updated 6 min readHardening and configuration

In short: Set session.upload_progress.enabled=0 in php.ini, in the PHP-FPM pool or in the Apache server configuration, never via ini_set() or .user.ini, and then restart all PHP workers. The measure only becomes permanent once the value is locked against being re-enabled, applies in every operating mode and every installed PHP version, and is rechecked after updates.

A small setting with a double effect

Rarely has a single PHP setting received so much attention. When php.net published the patches against PHP2Shell on 21 October 2026, session.upload_progress.enabled=0 was on the list of interim measures. Two days later came the notice about CVE-2026-115560, and the recommended remedy was the same setting.

Many administrators set it quickly in those days. Whether it takes effect everywhere is another question. Typical gaps are quickly listed: the value is only in the CLI configuration, a second PHP version was forgotten, or a hosting panel overwrote the file the next time it saved. This article shows how to implement the measure so that it still applies in three months.

Important beforehand: disabling it does not replace the PHP update. According to trade reports, session.upload_progress.enabled=0 alone does not close both PHP2Shell vulnerabilities. What exactly CVE-2026-115560 affects is explained on the page CVE-2026-115560: session upload progress notice.

What the feature does and who needs it

Session upload progress continuously writes the progress into the session during a file upload so that an application can display a progress bar. In PHP the feature is enabled by default. The PHP manual itself points out that file and field names supplied by the sender land unchecked in session storage, and recommends disabling the feature if the application does not use it.

Whether your application uses it can be found out with a purely read-only search of the code:

# Searches for uses of the progress feature in the application code
grep -rn --include="*.php" -e "upload_progress" -e "PHP_SESSION_UPLOAD_PROGRESS" /var/www/

If the search finds nothing, you can disable the feature without noticeable consequences. If there are hits, the application loses only the progress display, not the upload. Modern forms usually measure progress in the browser anyway.

Setting session.upload_progress.enabled in the right place

According to the PHP manual, the setting has the mode INI_PERDIR. This means it can be set in php.ini, in the server configuration, in .htaccess (mod_php only) and in .user.ini (FPM and CGI only), but not at runtime. php.net expressly rules out .user.ini as a place for the measure. The following table shows the sensible places per operating mode.

Operating mode Recommended place Locks against overriding? Restart afterwards
PHP-FPM pool file with php_admin_flag yes each FPM service
PHP-FPM php.ini of the FPM SAPI no, .user.ini could override each FPM service
Apache with mod_php VirtualHost or server configuration with php_admin_flag yes Apache fully
php-cgi, LiteSpeed, FrankenPHP php.ini of the respective runtime check depending on setup all processes of the runtime
Docker image separate file in /usr/local/etc/php/conf.d/ at build time yes, if no override is allowed recreate the container

The two robust variants look like this:

; PHP-FPM, e.g. /etc/php/8.3/fpm/pool.d/seite1.conf
php_admin_flag[session.upload_progress.enabled] = off
# Apache with mod_php, in the VirtualHost or server-wide
<IfModule php_module>
    php_admin_flag session.upload_progress.enabled off
</IfModule>

It is also worth adding the entry to the php.ini of every web SAPI as a base value. Then the setting also applies to new pools that someone creates later. Why php_admin_flag makes the difference is described in the article php_admin_value: locking settings against overrides.

Verifying effectiveness in the web context

The command line often reads a different php.ini than the web server. A php -i therefore proves little. Even php-fpm8.3 -i shows only the php.ini values, not the entries from the pools. Only a query that actually runs through the pool is reliable.

Proceed as follows:

  1. Restart all PHP services, for example systemctl restart php8.3-fpm, or Apache with mod_php. Without a restart the old value keeps running.
  2. Place a short test file with a random name in the web root that outputs only the current value.
  3. Call the file once via the real domain and note the result.
  4. Delete the file immediately and repeat the step for every website and every pool.
<?php
// Test file: place only briefly, then delete immediately
header('Content-Type: text/plain');
echo 'session.upload_progress.enabled = ', var_export(ini_get('session.upload_progress.enabled'), true), "\n";
echo 'PHP ', PHP_VERSION, ' / SAPI ', PHP_SAPI, "\n";

An empty value or '0' is expected. If it shows '1', your setting does not take effect in this pool. After a PHP update, also check that all workers have been restarted, as described under Restarting PHP-FPM and all workers.

Important

Never leave test files in place. They reveal versions and configuration and are a popular target of automated scans.

So that the setting stays permanent

Most relapses are caused not by attackers but by operations. A new pool is copied from an old template, a package update creates a new php.ini, or someone switches the PHP version in the hosting panel. Fixed habits help against such relapses.

  • Cover all versions: On many servers several PHP versions run in parallel. Each has its own configuration folders and needs the entry.
  • Adapt templates: Pool templates, Ansible roles, Dockerfiles and panel templates contain the value so that new websites inherit it automatically.
  • Use panel settings: In hosting panels the value belongs in the additional directives provided by the panel, otherwise the next change overwrites the manual work.
  • Check after updates: The check from the previous section belongs on the checklist of every PHP update.
  • Document: Record date, server, pools and result. This helps later with management, insurers or auditors.

Anyone who does not use .user.ini at all can switch off reading such files completely with user_ini.filename = in php.ini. However, this affects all settings that applications place there. Test this step beforehand, especially with CMS that write their own .user.ini files.

The other interim measures from php.net, such as the limits for post_max_size and the memory limit via cgroup, are collected under Immediate measures if you cannot patch yet. How PHP arranges its configuration levels in general is explained in php.ini explained.

How does PHP SOS help?

  • Take stock: We determine all PHP versions, operating modes and pools on your servers and read out the effective values in the web context.
  • Set cleanly: We enter the setting, locked, in pools and server configuration and restart all workers in a controlled way.
  • Test function: We check upload forms and media management after the changeover.
  • Prevent relapses: We adapt templates, deployments and panel settings and document the state as part of server hardening.

Frequently asked questions

Why does session.upload_progress.enabled=0 not work via ini_set()?

According to the PHP manual, the setting belongs to the mode INI_PERDIR. It therefore cannot be changed at runtime with ini_set() at all. php.net names php.ini, the FPM pool or the server configuration as the right places and expressly rules out .user.ini.

Do file uploads still work after disabling it?

Yes. Only the progress report that PHP writes into the session during an upload is switched off. The upload itself continues. Only applications that build their progress bar exactly on this PHP feature are affected.

Can an application switch the feature back on?

Via an .htaccess file with mod_php or a .user.ini with PHP-FPM this is possible in principle, as long as the value is not locked. With php_admin_flag in the pool or in the Apache configuration you prevent that.

Do I have to reset the value after the next PHP update?

No, that is not necessary. Most applications do not need the feature, and the PHP manual itself advises disabling it in such cases. After each update, just check that the value still applies.

Sources

Immediate contact

Every hour counts. Write to us now.

Briefly describe your system, PHP version and observation. We will get back to you, clarify the situation and work remotely until the incident is closed and documented.

Immediate help