Stopgap settings
PHP2Shell Temporary Mitigations: What Buys Days and What Only Looks Busy
Sometimes the update cannot happen today. The host is slow, the app is fragile, the only person with the password is on a plane. The PHP project published a short list of settings for exactly that moment, and it was careful to say what the list is not.
October 23, 2026 · 10 min read
The short answer
If you cannot update PHP today, the PHP project lists partial measures: memory_limit = -1 with a container memory cap, a low post_max_size, request limits at the proxy, session.upload_progress.enabled = 0, and on PHP 8.5 fatal_error_backtraces = 0, each followed by a full worker restart. Add a firewall rule. None of it is a fix. Update within days.
On this page
Sandbags are for the night of the flood
The PHP project's release notes contain one sentence worth taping to the monitor: "There are no complete mitigations, updating is the only safe choice." Its advisory then lists measures that, in its words, reduce exposure to specific attack paths but do not make an installation safe. That is an honest description of a sandbag. It keeps some of the water out. Nobody lives behind sandbags for a season.
So treat everything on this page as a bridge to the update, with a date at the far end. The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, and the shared hosting and VPS and Docker guides cover getting there. If you do not yet know which PHP you run, the vulnerability check takes ten minutes. Then come back here only if the answer is "vulnerable, and stuck for now."
A mitigation is a promise to patch, written in configuration.
Where each setting cuts the chain
The two bugs work as a relay. An anonymous visitor sends a crafted request, usually a multipart upload, which PHP starts parsing before your application sees anything. Push PHP into an out-of-memory error at the wrong moment and internal request data is left half built (CVE-2026-109618). Or leave request-owned state pointing at memory that has already been freed, so the next request on the same worker picks it up (CVE-2026-109619). Either way the attacker's data ends up where PHP expected its own.
An anonymous POST
No login, no password. One crafted upload request to any PHP page.
PHP parses the upload
Before your site's code runs, PHP reads the multipart body and tracks upload progress.
stops here
Memory runs out mid-step
A fatal error leaves request data half built, or freed memory still referenced.
The next request inherits it
The same worker reuses that stale state, and the attacker's code runs on your server.
Read the diagram and the logic of the settings becomes plain. Removing the memory limit attacks the out-of-memory trigger. Smaller request bodies and fewer parts shrink the parsing step. Turning off upload progress closes the confirmed session paths. Restarting workers flushes any state already planted. Each one narrows a box. None of them removes the stale-state flaw underneath.
The PHP project's list, line by line
These come from the PHP project's October 21 advisory. Set them in the configuration that loads before a request is parsed: the main php.ini, the PHP-FPM pool file, or the Apache virtual host. Per-directory tricks arrive too late or can be overridden by the very code you are trying to protect.
| Where to set it | What it narrows | The catch | |
|---|---|---|---|
| `memory_limit = -1` | `php_admin_value[memory_limit] = -1` in the FPM pool or Apache config, so apps cannot override it | The PHP memory-limit failure an attacker can steer | A real allocation failure can still reach the bug; check no pool or app sets a finite limit back |
| A container or cgroup memory limit | Docker, systemd or the orchestrator, ideally killing only the affected worker | Keeps the server alive once PHP has no limit of its own | Do not substitute RLIMIT_AS or RLIMIT_DATA, which can cause the vulnerable failure |
| `post_max_size = 8M` (no uploads) or `32M` (uploads) | php.ini or the pool, with `upload_max_filesize` set below it | The size of what an attacker can make PHP parse | Big uploads stop working, often as a failed image upload; tell staff first |
| Request limits at the web server or proxy | Request size, input fields, multipart parts, headers and nesting depth | Oversized or oddly shaped requests before PHP sees them | Must also cover requests with no usable Content-Length |
| `session.upload_progress.enabled = 0` | php.ini, the FPM pool or server config; never `ini_set()` or an FPM `.user.ini` | The confirmed session upload-progress paths | Other variants stay open; restart every worker afterward |
| `fatal_error_backtraces = 0` | PHP 8.5 only, in php.ini or the pool | The confirmed fatal backtrace path | That path only; restart every worker afterward |
Two more items from the advisory are code chores, not switches. Remove invalid or deprecated settings applied per request that print diagnostics before initialization. And fix the fatal errors and execution timeouts an outsider can trigger, including failures in callbacks, upload and import handling, and cleanup. If your error log is a wall of deprecation notices, this is the week to read it.
- 1
Open the pool or virtual host file
On PHP-FPM, edit the pool file for the site, often named www.conf. On Apache with mod_php, edit the virtual host or the main server config.
- 2
Add the admin values
Add `php_admin_value[memory_limit] = -1`, `php_admin_flag[session.upload_progress.enabled] = off` and the post size lines. Admin values cannot be changed later by the application.
- 3
Cap memory outside PHP
Set a container or cgroup memory limit for the PHP service so an unbounded worker cannot take the whole machine with it.
- 4
Test the configuration
Run the FPM config test (`php-fpm8.3 -t` on Debian and Ubuntu, `php-fpm -t` elsewhere) or `apachectl configtest` before restarting anything.
- 5
Restart every worker
Restart the FPM service or Apache. A setting that only new workers see is a setting half the traffic ignores.
- 6
Confirm in phpinfo
Load a password-protected phpinfo page and read the Local and Master values for each setting, then delete the page.
Shared hosting, a VPS and Docker each hide the switch somewhere else
On a VPS you own every file in the list above. On shared hosting you often own none of the ones that matter. Control panels tend to expose per-directory settings, which the PHP project specifically says not to rely on for upload progress, so the honest move is a support ticket asking the host to apply the advisory's server-level settings to your account, in writing, with a date for the real update. The template is on the shared hosting page.

In Docker, configuration baked into the image is the only kind that survives a redeploy. Copy an ini file into the image's PHP configuration directory and the pool settings into the FPM config, rebuild, and replace the containers. Set the memory cap on the container itself. Then put a reminder on the calendar to delete the workaround when the image moves to a patched base, because temporary settings in a Dockerfile have a way of becoming permanent architecture.
Firewall rules: the bouncer, not the lock
A web application firewall sits in front of the server and drops requests that look like the attack. According to Wiz Research, several edge and cloud companies (Cloudflare, Fastly, Google and Vercel among them) shipped ready-made protections and advice for teams that could not update right away. Google Cloud's advice covers Cloud Armor, its container services and App Engine. Cloudflare's own write-up says its protections were deployed automatically on all plans with the WAF turned on, Free included.
Cloudflare
Protected by default where the WAF is on. Paid plans should confirm the Managed Ruleset is set to block. Cloudflare reports attackers already mutating payloads to slip past it.
Other edge networks
Fastly, Vercel and others published their own guidance. Check your provider's advisory and whether the rule blocks or only logs.
Google Cloud
Published advice for Cloud Armor rules and for PHP running in its container and App Engine products. Useful if your PHP already sits behind a Google load balancer.
Your host's firewall
Ask whether the host added a server-level rule, and get the answer in writing. A promise on the phone is not a rule.
Two caveats decide whether the rule protects anything. First, a firewall only inspects traffic that passes through it. If the server's own address answers requests directly, an attacker can walk around the bouncer, so lock the origin to accept web traffic only from the firewall provider. Second, rules chase patterns, and patterns mutate. Cloudflare says plainly that customers should still patch PHP. When the company selling the bouncer tells you to change the locks, change the locks.
What none of this does
Buys real time
- Upload progress turned off at the server level, then every worker restarted
- An unbounded PHP memory limit paired with a container or cgroup cap
- Request size and part-count limits at the proxy
- A firewall rule in block mode, with the origin closed to direct traffic
Only looks busy
- Hiding errors with error_reporting, display_errors or the @ operator
- Calling `ini_set()` from the application, which runs after parsing
- A security plugin, which lives inside the PHP it is meant to guard
- Hiding the X-Powered-By header, which hides nothing from the bug
None of it cleans a server that was reached before you acted, either. Wiz showed that the bugs can also leak process memory without running code, and leaked memory can include passwords, tokens and API keys. If the server was exposed for days, read the signs of compromise and plan to rotate the secrets it could see. Our malware removal and security service handles the cleanup when there is something to clean.
Put a date on the duct tape
Attempts against sensors and honeypots began within a day of disclosure, most aimed at the upload-progress path. As of October 22, no confirmed compromise had been made public, which is a statement about one Thursday, not about next month. CrowdStrike's chief executive told CNBC on October 23 that the industry "will see a lot of breaches in coming months" from this vulnerability. Mitigations are measured in days. The problem is measured in months. Patching today costs an afternoon; a breach next spring costs a great deal more.
- Today: apply the settings above, restart every worker, and confirm them in phpinfo.
- Within 48 hours: get a written date for the PHP update from whoever runs the server.
- Within a week: run the update, test the site, and remove the workarounds you no longer need.
- After that: check for compromise, decide whether this site should still run PHP in public, and hand the next update to someone with a hosting and maintenance plan.
If the update keeps slipping because the site might break, that is a fixable problem. A WordPress site that falls over after a PHP update is a fixed $249 through Fix It Now, with work starting within one business day of payment and a full refund if we can't fix it. Our emergency fix applies these settings when the update must wait, then does the update. Sites stuck on end-of-life PHP get a plan. And if you would rather never repeat this week, a Next.js front end takes PHP off the public internet. The full map is on the PHP2Shell hub.
Questions owners ask about PHP2Shell
No. In the PHP project's own words, nothing short of the update is a complete mitigation. Its interim settings, such as turning off session upload progress and lowering post_max_size, narrow specific attack paths. Use them for days while you schedule the update to 8.2.35, 8.3.36, 8.4.27, 8.5.12 or a patched distribution build.
No. Both run too late or can be overridden. The PHP project wants the switch flipped where it takes effect before a request is parsed: the main php.ini, the PHP-FPM pool file, or the web server's own configuration. After changing it, restart every PHP worker so no running process keeps the old setting.
Cloudflare says its WAF protections were deployed automatically on all plans with the WAF enabled, including Free, and that paid plans should confirm the Managed Ruleset blocks. The rule only covers traffic routed through Cloudflare, attackers are already mutating payloads, and Cloudflare itself says to patch PHP anyway.
It can let one runaway PHP process use far more memory than before, which is why the PHP project pairs it with a container or cgroup memory limit, ideally one that kills only the affected worker. Do not use RLIMIT_AS or RLIMIT_DATA as the cap, because those can trigger the very failure the bug needs.
No. The PHP project says hiding diagnostics with error_reporting, display_errors or the @ operator does not help. What it suggests instead is removing invalid or deprecated per-request settings that emit diagnostics before initialization, and fixing fatal errors and timeouts that outsiders can trigger.
Days, not weeks. Attack attempts started within a day of disclosure and attackers are adapting to firewall rules. Set the interim settings now, get a written update date from your host or server admin, and patch within the week. Our emergency fix can apply both the stopgap and the update.
Keep reading
- Emergency servicePHP2Shell Emergency Fix: We Patch Your PHP, Test the Site and Check for IntrudersWe update PHP to a fixed release, test every page, check for signs of a break-in and clean up if needed. WordPress fixes from $249, paid on the page.
- The long-term fixNobody Can Exploit PHP on a Site That Does Not Run It: The Next.js Way Out of PHP2ShellKeep WordPress private behind a Next.js front end, or drop PHP for Athena CMS. What each removes, what carries over, the honest limits and the prices.
- Check your exposureAm I Affected by PHP2Shell? Find Your PHP Version and Read the ResultFive ways to find the PHP version and SAPI behind your site, a table that turns the number into a next step, and which sites PHP2Shell cannot touch.
- Shared hostingPatching PHP2Shell on Shared Hosting: cPanel, Plesk and Managed WordPressOn shared hosting your host patches PHP for PHP2Shell. How to confirm it in cPanel or Plesk, what to ask for in writing, and what breaks on newer PHP.
- Server patch guidePatch PHP2Shell on a VPS or in Docker: Packages, Restarts and ProofPatch PHP2Shell on Debian, Ubuntu, RHEL, Docker, FrankenPHP and LiteSpeed: which packages, which restarts, and how to prove the fix landed.
- CMS owners' briefingPHP2Shell on WordPress, Drupal and Joomla: Your CMS Is Current. Is Your PHP?Why a fully updated WordPress, Drupal or Joomla site can still fall to PHP2Shell, why security plugins cannot fix it, and what to update first.
- Everything in PHP2ShellSee the section
Get the stopgap in today and the fix in this week
Tell us where the site runs and what is blocking the update. We will apply the interim settings now and give you a date for the real patch.
Which of these sounds like you? (pick any)
Rather talk now? Call (210) 346-0848.