Two PHP bugs a security plugin can’t see, and what actually keeps WordPress safe

Two critical PHP bugs published on 21 October run before WordPress does, so no security plugin sees them. What I changed on this site’s own server while the host caught up, where WordPress sites actually get broken into, and which popular security habits are theatre.

  • Oct 27, 2026
  • 10 min read
A glowing WordPress logo inside a glass cube of circuitry, with CVE labels floating in the dark around it

Most WordPress sites aren’t broken into through WordPress. In 2025, 91% of newly reported WordPress vulnerabilities were in plugins and 9% in themes; the core had six, all low priority. This week added a different kind: two critical bugs in PHP itself, CVE-2026-109618 and CVE-2026-109619, published on 21 October. They sit below WordPress, so no security plugin ever sees the request that triggers them. What protects a site is the same in both cases, and it isn’t what most security checklists lead with: fast updates for the code that runs, fewer things that can run, and knowing what your host actually installed.

Key takeaways
  • Ask your host whether your PHP has the 21 October fixes. 8.2.35, 8.3.36, 8.4.27 and 8.5.12 are fixed, but many hosts backport the fix under the old version number, so php -v alone doesn’t answer it.
  • Turn off session upload progress unless you use it. It is the path the public exploit tool takes, and WordPress doesn’t need it.
  • Spend the rest of your effort on plugins: fewer of them, maintained ones, updated within days. That is where the vulnerabilities are.
  • A hidden login URL, a renamed table prefix and a security plugin stop none of this. They aren’t useless; they just aren’t the defence.

What the two PHP bugs do

The PHP project published both on 21 October with a CVSS 4.0 score of 9.2. Neither needs a login, and the researchers who found them call the pair PHP2Shell.

  • CVE-2026-109618. When PHP runs out of memory at the wrong moment, it jumps out of what it was doing and leaves request memory half-built, and the cleanup that runs afterwards trusts it. The confirmed way to get there is a crafted multipart request, the format browsers use to upload files, which PHP parses before any of your code runs. Full remote code execution was shown against Apache with mod_php and default limits; for PHP-FPM and LiteSpeed the advisory rates it likely but not demonstrated.
  • CVE-2026-109619. A PHP worker keeps some state between requests. When a request dies at the wrong moment, that state can point at memory that has already been freed, and the next request on the same worker can use it. Two confirmed ways in run before your code: INI warnings, and session upload progress, a feature that is on by default and works without any session_start() call.

A tool for the upload-progress path was circulating on the day of disclosure. Imunify360, the firewall on many shared hosts, shipped a rule against that request the same day; CloudLinux, which makes it, also wrote that none of its rules block the out-of-memory path yet.

Why a security plugin can’t help here

A WordPress security plugin is PHP code that runs inside WordPress. By the time it loads, PHP has already read the request, parsed its multipart body and handled upload progress. Both bugs fire in that earlier stage; on mod_php, before any application code at all. The only layers that can stop such a request sit in front of PHP: the web server, the host’s firewall, a CDN. And hosting firewalls aren’t a safe bet either: in Patchstack’s tests last year, typical hosting defences blocked 12% of WordPress-specific attacks.

What I did on this site’s own server

The CMS behind this site is WordPress on shared hosting, behind LiteSpeed. On disclosure day it reported PHP 8.3.35, and every PHP version the host offered was one release behind the fix: 8.2.34, 8.3.35, 8.4.26, 8.5.11. Switching versions wouldn’t have helped, so I looked at what the account itself could change.

  • Session upload progress was already off in the host’s php.ini. That closes the path the public tool uses.
  • Memory limits were the opposite of helpful: memory_limit and post_max_size both at 2048M. The advisory’s main workaround, memory_limit=-1, wasn’t available; the host’s panel only accepts 1024M to 2048M.
  • .user.ini is switched off on this host (user_ini.filename is empty in phpinfo), so per-folder PHP settings weren’t an option either.
  • Multipart turned out to be the lever. Nothing legitimate sends it to this WordPress: the public site is a separate front end that talks to WordPress in JSON, and media arrives by URL, not by upload. So WordPress now refuses multipart unless it comes from my own address.
# PHP parses a multipart body before WordPress runs (CVE-2026-109618).
# Nothing here needs it except my own uploads in wp-admin.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:Content-Type} multipart/ [NC]
RewriteCond %{REMOTE_ADDR} !^203\.0\.113\.10$
RewriteRule .* - [F,L]
</IfModule>

Two details mattered. LiteSpeed on this host ignores <Files> and Require rules in .htaccess, so the block has to be a rewrite rule, and a rule that silently does nothing looks exactly like one that works. And a block is only tested once you test it from somewhere else. From another server, a multipart request got 403 while a JSON request and a normal page load went through as before.

# From a machine that is NOT on the allowed address
curl -s -o /dev/null -w '%{http_code}\n' -F probe=1 https://cms.example.com/wp-json/
# 403: the multipart request is refused
curl -s -o /dev/null -w '%{http_code}\n' https://cms.example.com/wp-json/
# 200: everything else still works
Don’t copy the rule blind

Many form plugins send their submissions as multipart/form-data, even without a file field. On a typical WordPress site this rule breaks the contact form. Submit your form with the browser’s network tab open and check the request’s Content-Type first. If your forms use multipart, the fix is the PHP update, not the rule.

Two days later the host’s PHP still said 8.3.35, but its build date had changed to 21 October. That proved nothing either way: CloudLinux, whose alt-php packages many shared hosts run, first shipped the fix under the old version numbers, and Ubuntu 24.04 still calls its fixed PHP 8.3.6. A shared account can’t read the package changelog either. What it can read is the binary. The fix added a new error message, “Hard memory limit of … bytes exhausted”, for the second memory threshold that replaces the old jump-out, and a PHP without the fix doesn’t contain that text. On this host every PHP version now does, and the web server reports the same new build. The hole is closed; the multipart rule stays as a second layer, because here it costs nothing.

# Does this PHP contain the 21 October fix? 1 = yes, 0 = no (PHP 8.2 and newer)
grep -c -a "Hard memory limit of" "$(command -v php)"
# Check the binary the web server runs too: php-fpm, lsphp or php-cgi

Where WordPress sites actually get broken into

91%of new WordPress vulnerabilities in 2025 were in plugins; themes had 9%, the core six

46%had no fix from the developer when they were made public

5 hoursweighted median from disclosure to mass exploitation, for the most attacked ones

Patchstack counted 11,334 new vulnerabilities in the WordPress ecosystem in 2025, 42% more than the year before. Seven of the ten most exploited needed no login. Paid plugins aren’t safer: they made up 29% of valid reports, and about three quarters of those were exploitable in real attacks. So the questions that matter are about plugins: how many you run, who maintains them, how fast their updates reach your site, and what you do when one has a hole and no fix.

What to protect, in order

1. The plugins you run

Each active plugin adds endpoints that anyone on the internet can send requests to: AJAX actions, REST routes, form handlers. Fewer plugins is fewer doors.

  • Delete what you don’t use. A deactivated plugin’s files stay on the server, and some of them can still be requested directly.
  • Check who maintains each one. A plugin closed on wordpress.org gets no fixes. One without a release in a year is a question for its author, or a reason to replace it.
  • Update within days, not at the next maintenance window. Turn on auto-updates for plugins where a broken update would cost less than a late one.
  • When there’s no fix, a virtual patch from Patchstack or Wordfence covers the gap. Removing the plugin is the actual fix.
# What needs an update
wp plugin list --update=available --fields=name,version,update_version
# What is installed but not in use
wp plugin list --status=inactive --fields=name,version
# Did anyone change core, or plugin files from wordpress.org?
wp core verify-checksums
wp plugin verify-checksums --all
# Who can do everything
wp user list --role=administrator --fields=user_login,user_email,user_registered

2. The accounts that can change the site

  • Count the administrators. Accounts from a previous agency or freelancer are a common leftover. Remove them, or drop them to Editor.
  • Two-factor for every admin. The Two Factor plugin from WordPress contributors does it without extras.
  • Review application passwords. Each user’s profile lists them with the date they were last used. Revoke the ones nobody recognises.
  • Turn off the file editor, so a stolen admin login can’t edit PHP from the dashboard.
// No theme or plugin file editor in wp-admin
define( 'DISALLOW_FILE_EDIT', true );

3. The server under WordPress

  • A supported PHP branch, 8.2 or newer, on a host that ships security fixes in days. Ask them where they announce PHP updates.
  • Know what the website runs. Tools → Site Health → Info → Server shows the PHP version the web server uses. php -v over SSH can be a different binary.
  • Backups outside the hosting account, and a restore you have actually tried once.

4. The doors nobody uses

  • XML-RPC. If nothing on your site uses it, block xmlrpc.php. It is a favourite for password guessing.
  • The login page. If only a few people log in from known places, allow wp-login.php from their addresses only. On this site it answers one.
  • The user list. /wp-json/wp/v2/users lists everyone who has published a post, and on many sites the slug it shows is the login name. That is half of a login.

The myths

MythWhy it doesn’t holdDo this instead
“WordPress is insecure.”The core had six low-priority vulnerabilities in 2025. Plugins and themes had over 11,000.Judge a site by its plugin list, not its CMS.
“Hide the login URL.”It cuts bot noise in the logs. It does nothing about a plugin hole, and seven of the ten most exploited needed no login at all.Two-factor, and an address allow-list where you can.
“A security plugin has it covered.”It runs inside WordPress, after PHP has parsed the request. This week’s bugs fire before that.Fast updates, and a filter in front of PHP for the gap.
“Change the wp_ table prefix.”An attacker with SQL injection can read the table names from the database itself.Update or remove the plugin with the injection.
“Hide the WordPress version.”Mass exploitation doesn’t check versions; it sends the exploit to every site that answers.Hide it for tidiness, then update anyway.
“We’re too small to be a target.”Attacks are automated. About half of high-impact vulnerabilities were attacked within a day of going public.Treat a 20-page brochure site like any other.

If you do one thing this week

This week
  • Ask your host whether your PHP includes the 21 October fixes, by package release, not just by version number.
  • Open Site Health → Info → Server and note the PHP version the website really runs.
  • Set session.upload_progress.enabled to Off, or ask your host to.
  • Delete inactive plugins, and list the ones without a release in the last year.
  • Count your administrators and revoke application passwords nobody recognises.
  • Make sure a recent backup exists outside the hosting account.

The bigger version of hiding wp-admin

The login-URL trick is a small version of a good idea: the less of WordPress the public can reach, the less any bug in it matters. This site takes that idea all the way. Visitors get pages from a Next.js front end and never touch WordPress, which sits on its own subdomain where the login page answers one address, XML-RPC is refused and, since this week, so is multipart. A bug like PHP2Shell still has to be patched, but it no longer sits behind every page a visitor or a bot opens.

Related serviceKeep WordPress, take it off the public internetA headless Next.js front end: your team keeps writing in WordPress, visitors get fast pages, and WordPress itself sits out of their path.See the service

To see what your own site shows from outside, the free scan on this site checks the core and plugin versions it can see, an open XML-RPC, a public user list, exposed backup and log files, and a PHP version past its end of life when the server announces it.

Less WordPress in publicKeep editing in WordPress, and take it off the path of every visitor and botHeadless Next.js siteRun the free scan
Share@
Common questions

Questions from this article.

Something else?Write a line about your site. You’ll get a reply from me within one business day.

If it runs PHP older than 8.2.35, 8.3.36, 8.4.27 or 8.5.12 without a backported fix, yes, whatever plugins you use. Hosts that backport often keep the old version number, so ask your host which package release you are on and whether it includes the 21 October fixes.

No. A plugin runs inside WordPress, after PHP has already parsed the request, and both bugs fire before that. The PHP update, settings such as session.upload_progress.enabled, or a filter in front of PHP are what can act on them.

It is harmless and cuts bot noise in your logs, but it is not protection: most exploited plugin holes need no login at all. Two-factor authentication, and allowing the login page only from known addresses where you can, do much more.

For most plugins, yes: a late update is usually riskier than a broken one, and since WordPress 6.6 an auto-update that causes a fatal error is rolled back. Keep manual, tested updates for the few plugins your forms, shop or tracking depend on, and do those within days.

Keep reading

More on speed and leads.

All insights