PHP2Shell Interim Mitigations: Every php.ini Setting Explained
PHP2Shell Interim Mitigations: Every php.ini Setting Explained

As of 23 October 2026, the only complete fix for PHP2Shell is updating to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or to a vendor package with the same patch. If you cannot update today, PHP's official advisory lists settings that make the known attacks harder. In PHP's words, they "reduce exposure to specific attack paths but do not make an installation safe."
The main ones are session.upload_progress.enabled=0 for CVE-2026-109619 and memory_limit=-1 plus a low post_max_size for CVE-2026-109618. Each has conditions. They must go in php.ini, the PHP-FPM pool or the server configuration, not in ini_set() or a .user.ini file. You must restart every PHP worker afterwards. And memory_limit=-1 has side effects you need to plan for.
This guide goes through each setting in the official advisory: what it blocks, what it can break, and how to apply it. Use it to buy time while you update, not instead of updating.
Key Takeaways
- PHP's release notes say: "There are no complete mitigations, updating is the only safe choice." Every setting here is partial.
- Set mitigations in php.ini, an FPM pool or the server configuration. PHP says: "Do not rely on ini_set() or FPM .user.ini."
- Restart every PHP worker after any change, or the old settings stay in effect.
- memory_limit=-1 removes PHP's memory cap. Add a container or cgroup limit, and never use RLIMIT_AS or RLIMIT_DATA instead.
- Turning off session upload progress breaks only PHP's built-in upload progress bars. PHP suggests keeping it off even after patching if you don't need it.
- WAF rules from Cloudflare, Barracuda and others are an extra layer, not a fix. If you can neither patch nor mitigate, EU and US agencies say to take the system offline or isolate it.
What These Mitigations Can and Cannot Do
PHP2Shell is two bugs in the PHP engine. CVE-2026-109618 involves out-of-memory handling during request parsing. CVE-2026-109619 involves stale internal state that one request can leave for the next request on the same worker. Our explainers for CVE-2026-109618 and CVE-2026-109619 cover each one.
The mitigations close specific paths that researchers proved. They do not close the bugs. PHP's advisory for CVE-2026-109619 warns: "There is no complete generic configuration mitigation as an application, extension or server path may publish stale state or consume it without a predictable log entry."
Some security firms go further. watchTowr says "Mitigations that involve changes to .ini files should be understood to be ineffective and not suitable to prevent exploitation." Datadog says common community mitigations "don't fully protect you." Beazley says turning off upload progress "mitigates the attack vector in the most commonly produced exploits and proof of concept examples we have observed since publication." Taken together, these settings are worth applying if you can't patch, but no source calls them complete.
Where to Set Them (and Where Not To)
Where you put a setting decides whether it works. PHP's advisory says to use "php.ini, an FPM pool or server configuration that applies before request parsing. Do not rely on ini_set() or FPM .user.ini."
- php.ini or a file in the PHP configuration folder. AlmaLinux, for example, documents adding a file under /etc/php.d/.
- PHP-FPM pool. Use php_admin_value. The PHP-FPM configuration manual says settings "defined with php_admin_value and php_admin_flag cannot be overridden with ini_set()."
- Apache configuration (mod_php). php_admin_value in the server or virtual host configuration. PHP's manual says it "can not be used in .htaccess files" and "can not be overridden by .htaccess or ini_set()."
Why not .user.ini? PHP's advisory explains that ".user.ini is applied after normal initialization." The vulnerable code runs before that point, so a setting there arrives too late. The same goes for ini_set() in application code, including settings changed by a WordPress plugin.
On shared hosting you usually can't edit php.ini or FPM pools. Ask your host to apply these at the server level, or to patch, which is better.
All Settings at a Glance
| Setting (as PHP states it) | CVE | What it blocks | What it can break |
|---|---|---|---|
| session.upload_progress.enabled=0 | CVE-2026-109619 | "the confirmed session paths but not other variants" | PHP's built-in session upload progress bars |
| fatal_error_backtraces=0 (PHP 8.5 only) | CVE-2026-109619 | "the confirmed fatal backtrace path only" | Backtraces in fatal error messages |
| memory_limit=-1, set so apps can't override it | CVE-2026-109618 | "the controllable PHP memory limit failure" | PHP no longer caps memory per request; workers can exhaust server memory |
| post_max_size = 8M (no uploads) or 32M (uploads), upload_max_filesize below it | CVE-2026-109618 | Reduces room for oversized multipart requests | Larger uploads and large form posts |
| Web server or proxy limits on request size, field count, multipart parts, headers and nesting depth | CVE-2026-109618 | Stops oversized or deeply nested requests before PHP | Complex forms and big uploads, if set too low |
| Container or cgroup memory limit (never RLIMIT_AS or RLIMIT_DATA) | CVE-2026-109618 | An availability boundary when memory_limit=-1 | Can kill every worker if the whole group is limited |
| Remove invalid or deprecated per-request settings | CVE-2026-109619 | Early diagnostics that can consume stale state | Usually nothing, once the bad settings are found |
| pm.max_requests=1 (from PHP's GHSA) | CVE-2026-109619 | Limits each worker to one request | Severe performance cost |
Settings for CVE-2026-109618 (Out-of-Memory Corruption)
memory_limit=-1
PHP's advisory says: "Set memory_limit=-1, preferably in a way applications can't override, such as php_admin_value in the FPM pool or Apache configuration, and check that no pool, directory or application setting puts a finite limit back. This removes the controllable PHP memory limit failure, but an underlying allocation failure can still reach the vulnerable path."
An example FPM pool line, as AlmaLinux documents it:
php_admin_value[memory_limit] = -1
Do not use this lightly. The CVE-2026-109618 advisory calls it "the primary configuration mitigation" but also "not a complete mitigation." The side effects are real:
- Calif: it "removes PHP's memory cap, increasing the risk of memory exhaustion."
- php2shell.com: "memory-exhausted workers may be terminated, interrupting requests and affecting stability and availability of the server."
- Any pool, directory or application setting that sets a finite memory limit again cancels the mitigation. Setting it with php_admin_value stops applications from changing it with ini_set(), but check every pool and virtual host.
Put a container or cgroup limit around it, never RLIMIT
Because PHP is no longer capping memory, PHP says: "Use a container or cgroup limit as an availability boundary, preferably with a policy that kills only the affected worker. Do not substitute RLIMIT_AS or RLIMIT_DATA, as these can cause the vulnerable allocation failure."
The advisory explains the RLIMIT problem: those limits "will cause mmap() to fail once the memory limit is reached, triggering the vulnerable longjmp() path." In other words, RLIMIT would recreate the exact failure the mitigation is meant to avoid. It also warns that "killing a container or cgroup can also kill the master and every worker, unless each worker has its own group."
A low post_max_size
PHP's advisory says: "Set a low post_max_size. For applications that don't require file uploads, set post_max_size = 8M. If file uploads are necessary, set post_max_size = 32M. Keep upload_max_filesize below post_max_size."
What breaks: uploads and form posts larger than the limit. php2shell.com says "test legitimate upload flows." Fastly notes that 8M is PHP's default "but many production deployments have raised it," so sites that accept large media, PDFs or imports will notice.
Limits at the web server or proxy
PHP's advisory: "Consider enforcing limits at the web server or proxy level for decoded request size, input field count, multipart part count, header count, and nesting depth. These limits must also cover requests without a usable Content-Length." The GHSA also suggests reducing max_input_nesting_level, and php2shell.com warns that "Complex forms may require a higher limit."
The GHSA adds: "If the application does not use multipart form data, block such requests at the frontend before they reach PHP." Multipart is the format browsers use for file upload forms, so only do this for sites with no upload forms.
Settings for CVE-2026-109619 (Stale Global State)
session.upload_progress.enabled=0
PHP's advisory: "Set session.upload_progress.enabled=0 and restart every worker. Use php.ini, an FPM pool or server configuration that applies before request parsing. Do not rely on ini_set() or FPM .user.ini. This blocks the confirmed session paths but not other variants."
An example php.ini line:
session.upload_progress.enabled = 0
This feature is on by default, and the advisory says no application call to session_start() is needed for the attack. What breaks is narrow. Fastly says it "Only affects applications that show real-time upload progress bars using PHP's built-in session mechanism. Most applications that show upload progress use JavaScript-based approaches instead."
Keep it off after patching. The CVE-2026-109619 advisory says "It might be prudent to set session.upload_progress.enabled=0 if you don't need this feature even after applying the patch." On 23 October PHP also published an informational advisory for CVE-2026-115560, which affects fully patched releases under an unusual configuration. PHP suggests this same setting "until the next regular bugfix release." If you already applied it, PHP says "keep it in place and no further action is needed."
fatal_error_backtraces=0 (PHP 8.5 only)
PHP's advisory: "On PHP 8.5, set fatal_error_backtraces=0 and restart every worker. This blocks the confirmed fatal backtrace path only." The setting exists only from PHP 8.5.0. What changes: fatal error messages no longer include a backtrace, which makes debugging a little harder.
Remove settings that produce early warnings
PHP's advisory: "Remove invalid or deprecated settings applied per request that emit diagnostics before initialization. Hiding diagnostics with error_reporting, display_errors or @ does not help." Per-request settings include .htaccess php_value lines under mod_php and PHP_VALUE parameters that nginx or Apache pass to PHP-FPM. Hiding the warning doesn't help because, as the GHSA says, the stale state is used "before PHP decides whether to report, display or log the warning."
Fix fatal errors and timeouts attackers can trigger
PHP's advisory: "Fix attacker-reachable fatal errors and execution timeouts, including failures in callbacks, upload or import processing and cleanup." This is developer work. Your error logs show which routes fail often.
pm.max_requests=1
The GHSA says: "If performance is not a factor, consider limiting the number of requests a worker may execute using pm.max_requests=1." This stops one request's leftovers reaching the next. Fastly says it comes "at severe performance cost," so treat it as a last resort where speed matters less than exposure.
Restart Every Worker, Then Check
None of these settings take effect until PHP restarts. Restart PHP-FPM and Apache (if it runs mod_php), for example:
sudo systemctl restart php8.3-fpm (replace 8.3 with your version)
Then confirm the setting is live for the website, not just the command line. A temporary phpinfo() page shows the effective values; delete it right after. Our guide on how to check your PHP version explains that page and why the command-line PHP can differ.
WAF Rules: A Useful Extra Layer
A web application firewall (WAF) inspects requests before they reach your server. Several vendors shipped PHP2Shell rules. All of them say to patch anyway.
- Cloudflare says its rules are "deployed automatically on all plans with WAF deployed, including Free users," and that paid-plan customers should confirm the Managed Ruleset is in block mode. It adds that "Customers should patch their PHP repos even with WAF protections." Its PHP2Shell post also notes that "Customers who have changed session.upload_progress.name are not covered by the WAF rule" for CVE-2026-115560.
- Barracuda says "Patching PHP is the only complete fix for PHP2Shell." Its PHP2Shell post says WAF-as-a-Service gets upload progress protections automatically, appliance customers must apply a policy, and "A WAF in monitoring or passive mode records traffic but does not block it."
- Imunify360 added blocking rules; CloudLinux says ruleset 8.88 adds rule 77049357 for the upload progress field.
Rules running inside WordPress or another application can't stand in for these. On mod_php the vulnerable code runs before any application code. Ask your host whether a server-level or edge WAF is in front of your site and in blocking mode.
If You Can't Patch or Mitigate: Isolate
Official agencies are clear on this. The EU joint statement says: "Where immediate remediation is not feasible, consider isolating exposed applications from public networks until fixes can be applied." The UK NCSC says that if you can't apply the mitigations, or they would take too long, "you should consider taking the system offline." CISA says organizations that cannot update, or that run PHP 8.1 or earlier, "should take PHP-based systems offline until they can be patched or updated."
Do it carefully. Beazley advises: "use a maintenance response or network restriction rather than disabling the PHP handler, which can expose application source code and credentials." Use a maintenance page, firewall rule or VPN-only access instead. If you are worried the site was attacked before you acted, see was my site hacked through PHP2Shell, and keep our incident response plan at hand.
When to Remove the Mitigations
Once you are on a fixed build (see PHP2Shell fixed versions) and every worker has restarted:
- Restore a finite memory_limit. The patch keeps PHP's ability to limit memory, so a normal memory limit is safe again and protects the server.
- Revisit post_max_size and proxy limits. The GHSA says these limits "reduce hard OOM and denial of service risk even after applying the patch." Loosen them only as far as your uploads need.
- Keep session.upload_progress.enabled=0 unless you use PHP's built-in progress bars, at least until PHP's next regular release fixes CVE-2026-115560.
- Undo pm.max_requests=1 once patched, since it carries a performance cost.
Conclusion
As of 23 October 2026, PHP's interim mitigations narrow the known PHP2Shell attack paths, but the PHP project, its advisories and independent researchers agree they are not a fix. Apply them in php.ini, the FPM pool or server configuration, restart every worker, plan for the side effects of memory_limit=-1, and keep a WAF in blocking mode if you have one. Then update PHP as soon as you can. If you need help applying mitigations safely or patching quickly, our emergency PHP patching team can step in. Every PHP2Shell guide is in our PHP2Shell Resource Center.
Frequently Asked Questions
Does setting session.upload_progress.enabled=0 make me safe?
No. PHP says it "blocks the confirmed session paths but not other variants." It is one of the most useful mitigations, and PHP suggests keeping it after patching, but only updating PHP fixes the vulnerabilities.
Can I add the mitigations to .user.ini or with ini_set()?
No. PHP's advisory says "Do not rely on ini_set() or FPM .user.ini." Those apply after the vulnerable code has already run. Use php.ini, the PHP-FPM pool or the web server configuration, and restart PHP.
Is memory_limit=-1 dangerous?
It has a real cost. It removes PHP's memory cap, so a runaway request can use up server memory and get workers killed. PHP pairs it with a container or cgroup limit and warns never to use RLIMIT_AS or RLIMIT_DATA instead.
Will turning off upload progress break my file uploads?
Normally not. It only affects progress bars built on PHP's own session upload progress feature. Fastly notes most sites show progress with JavaScript instead. File uploads themselves keep working.
Do I have to restart PHP after changing these settings?
Yes. PHP's advisory says to "restart every worker." Until workers restart, they keep the old settings.
Does a WAF protect me from PHP2Shell?
Partly. Cloudflare, Barracuda and Imunify360 have shipped rules that block known exploit patterns, and they help while you patch. Every one of those vendors still says to update PHP, and a WAF in monitoring mode blocks nothing.
I'm on shared hosting. Can I apply these myself?
Usually not, because they need server-level configuration. Ask your host to confirm the PHP2Shell patch is installed. If it isn't, ask them to apply these settings at the server level in the meantime.
Put this into action with eSEOspace
We help businesses grow with maintenance & support that actually performs. Explore the services behind this guide:
Get a FREE Audit
We'll perform a comprehensive SEO, AEO, GEO & CRO audit of your website — completely free — and show you exactly how to outrank your competitors.
Don't have a site yet? Get in touch →
Get a FREE GEO/AEO/SEO Audit
We'll analyze your site's SEO, GEO, AEO & CRO — completely free — and show you exactly how to get found across Google and AI answers.
Don't have a site yet? Get in touch →
Great — your audit is on the way!
We'll send your free SEO/GEO/AEO/CRO audit within the next few hours. Where should we send it?
You're all set! ✓
Your free audit is being prepared — check your inbox in the next few hours. Talk soon!
On this page
- Key Takeaways
- What These Mitigations Can and Cannot Do
- Where to Set Them (and Where Not To)
- All Settings at a Glance
- Settings for CVE-2026-109618 (Out-of-Memory Corruption)
- Settings for CVE-2026-109619 (Stale Global State)
- Restart Every Worker, Then Check
- WAF Rules: A Useful Extra Layer
- If You Can't Patch or Mitigate: Isolate
- When to Remove the Mitigations
- Conclusion
- Frequently Asked Questions





