session.upload_progress.enabled

Does session.upload_progress.enabled = 0 stop PHP2Shell?

Partly. It blocks the confirmed session-based paths of one of the two CVEs — and only if you set it in the right place and restart. It is a stopgap, not a fix.

Last reviewed 2026-10-22

The short answer

php.net: “This blocks the confirmed session paths but not other variants.” It does nothing for CVE-2026-109618. The workaround circulated widely before the patch; the release confirmed it was never complete. Patch PHP.

What the setting does

With upload progress enabled (the default), PHP watches multipart uploads for a special form field and writes progress into the user’s session while it is still parsing the request. That early, pre-initialisation session handling is exactly where PHP2Shell’s session-related use-after-free and memory leak live — including the leak of heap memory into the PHPSESSID cookie, which works even if your app never starts a session.

What it blocks and what it doesn’t

Attack pathBlocked?
Confirmed session upload-progress paths (CVE-2026-109619)Yes
Fatal-error backtrace path (PHP 8.5)No — also set fatal_error_backtraces = 0
Other stale-state variants (CVE-2026-109619)No
Out-of-memory corruption (CVE-2026-109618)No — see memory_limit / post_max_size

1. Check the current value

shell
# What php.ini says (CLI and FPM can differ — check both)
php -i | grep session.upload_progress.enabled
php-fpm8.3 -i | grep session.upload_progress.enabled    # adjust version

# Where the setting comes from
php --ini
grep -rn "upload_progress" /etc/php/ 2>/dev/null

# What the running site actually uses (FPM pool overrides are only visible here)
# <?php var_dump(ini_get('session.upload_progress.enabled'));

2. Set it where it actually applies

LocationWorks?Why
php.ini / conf.d drop-inYesApplies before request parsing.
FPM pool php_admin_flag / php_admin_valueYesPer pool; cannot be overridden by the app.
Apache vhost / server config (php_admin_flag)YesFor mod_php.
.user.iniNophp.net: do not rely on it — it may not apply before request parsing.
.htaccess php_flagNot recommendedPer-directory and overridable; use server config.
ini_set() in codeNoRuns after the request was already parsed.
config
; php.ini or conf.d drop-in, e.g. /etc/php/8.3/fpm/conf.d/99-php2shell.ini
session.upload_progress.enabled = 0

; or per FPM pool (/etc/php/8.3/fpm/pool.d/www.conf)
php_admin_flag[session.upload_progress.enabled] = off

; or Apache + mod_php (vhost or server config, not .htaccess)
php_admin_flag session.upload_progress.enabled off

3. Restart every worker

Running workers keep their old settings — and possibly already-corrupted state — until they restart.

shell
sudo systemctl restart php8.3-fpm      # every FPM version and pool you run
sudo systemctl restart apache2         # mod_php
sudo /scripts/restartsrv_apache_php_fpm   # cPanel
sudo systemctl restart plesk-php83-fpm # Plesk, per handler

Questions

Does session.upload_progress.enabled = 0 protect against PHP2Shell?+

Only partly. php.net says it “blocks the confirmed session paths but not other variants”. It does nothing for CVE-2026-109618. PHP core developer Gina Peter Banyard: “the only mitigation is patching/upgrading PHP.”

Can I set session.upload_progress.enabled in .user.ini or with ini_set()?+

No. Upload progress runs while PHP parses the request, before your code runs. php.net says to use php.ini, an FPM pool or server configuration that applies before request parsing, and explicitly not .user.ini or ini_set().

Will disabling upload progress break my site?+

Rarely. It only powers upload progress bars built on PHP’s session upload-progress feature. Most modern upload UIs track progress in the browser instead.

Should I turn it back on after patching?+

Only if you use it. php.net suggests leaving it disabled when unused, even on patched versions.

Related