# Disabling session.upload_progress: Correctly and Permanently

> Set session.upload_progress.enabled=0 correctly: where the value takes effect, how to lock it against being re-enabled and how to verify it safely in the web context.

Source: https://phpsos.de/en/blog/session-upload-progress-abschalten/  
As of: 25/10/2026  
Provider: PHP SOS, PHP emergency help and server security. Immediate help via WhatsApp: https://wa.me/491736494914?text=Hello%20PHP%20SOS%2C%20we%20need%20help%20with%20our%20PHP%20server.%20Company%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**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](https://phpsos.de/en/php2shell/cve-2026-115560/).

## 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:

```bash
# 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:

```ini
; PHP-FPM, e.g. /etc/php/8.3/fpm/pool.d/seite1.conf
php_admin_flag[session.upload_progress.enabled] = off
```

```apache
# 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](https://phpsos.de/en/blog/php-admin-value-sperren/).

## 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
<?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](https://phpsos.de/en/php2shell/php-fpm-neustart/).

> **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](https://phpsos.de/en/php2shell/sofortmassnahmen-ohne-patch/). How PHP arranges its configuration levels in general is explained in [php.ini explained](https://phpsos.de/en/php/php-ini-erklaert/).

## 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](https://phpsos.de/en/leistungen/server-haertung/).


## 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

- [php.net: Security announcements](https://www.php.net/)
- [PHP manual: Session configuration](https://www.php.net/manual/en/session.configuration.php)
- [PHP manual: .user.ini files](https://www.php.net/manual/en/configuration.file.per-user.php)
