PHP2Shell (CVE-2026-109618): what WordPress owners must do
Two PHP flaws fixed on 21 October 2026 — CVE-2026-109618 and CVE-2026-109619, nicknamed PHP2Shell — let an attacker run code on a server without logging in, and CISA confirmed they are being exploited. They are in PHP itself, so no WordPress or plugin update fixes them. Here is how to check your PHP version and what to update.
What was fixed, and why it matters
On 21 October 2026 the PHP project released 8.5.12, 8.4.27, 8.3.36 and 8.2.35 as a critical security release, after an advance notice the day before. They fix two vulnerabilities rated 9.2 (CVSS v4) that can allow unauthenticated remote code execution:
| CVE | What goes wrong | Advisory |
|---|---|---|
| CVE-2026-109618 | PHP running out of memory while it is still setting up a request — triggered by crafted multipart (form upload) data — leaves memory half-initialised, and request cleanup then uses it | GHSA-w8hw-w9fx-j79w |
| CVE-2026-109619 | State belonging to one request survives after its memory is freed, and the next request handled by the same worker uses it | GHSA-6wmf-4rv5-p3rp |
The dangerous part is where it happens: while PHP is reading the incoming request, before WordPress, a plugin or a security plugin has run a single line. Any URL that reaches PHP is enough. CISA added both CVEs to its Known Exploited Vulnerabilities catalogue on 26 October 2026, after successful remote code execution was reported against honeypot servers on 24 October.
Is your site affected?
Every PHP version before the fixed releases is affected. How exposed you are depends on how your server runs PHP:
| How PHP runs | Status per the advisory |
|---|---|
| Apache with mod_php | Confirmed: full remote code execution demonstrated with default settings |
| PHP-FPM (Nginx, most VPS and many hosts) | Susceptible from source analysis; no complete exploit demonstrated yet |
| LiteSpeed / LSAPI | Modelled on FPM; application-specific exploits considered likely |
| FrankenPHP | Likely susceptible |
“No complete exploit yet” is not a reason to wait. Update whatever the server type.
Check which PHP your site runs
In WordPress: Tools → Site Health → Info → Server → PHP version. On a server you manage:
php -v # the CLI version
apt list --installed 2>/dev/null | grep -E '^php[0-9.]+-(fpm|cli|common)'
# Fixed upstream releases: 8.5.12, 8.4.27, 8.3.36, 8.2.35 or laterTwo traps. First, the CLI and the web server can run different PHP versions — check the Site Health number, which is the one serving your pages. Second, Linux distributions often fix security bugs by patching their own package without moving to the new upstream number, so a Debian or Ubuntu package may report an older 8.x.y and still be fixed. For distribution packages, check the package changelog or the distribution’s security tracker for the two CVE numbers rather than the version string.
Update — and restart PHP
- Shared or managed hosting: the host updates PHP. Ask them, in writing, whether the PHP serving your site includes the fixes for CVE-2026-109618 and CVE-2026-109619. If your plan lets you choose a PHP version, choose a supported one (8.3, 8.4 or 8.5).
- Your own server: install the updated packages from your distribution or PHP repository, then restart PHP so running workers load the new code: systemctl restart php8.4-fpm (with your version), or restart Apache for mod_php. Until the workers restart, the old code is still the one answering requests.
- PHP 8.1 or older: the PHP project no longer releases these versions. It published minimal source backports for 7.4, 8.0 and 8.1, but the real fix is moving to a supported branch — PHP 8.2 itself reaches end of life on 31 December 2026.
Because the flaw is in PHP, no WordPress core, plugin or security-plugin update can fix it. Updating WordPress and plugins is still good practice; it simply does not close this hole.
If you cannot update today
The advisory is explicit that only updating is a complete fix. These reduce the risk in the meantime and must be set in php.ini or the FPM pool, not in .user.ini or with ini_set(), because the bug triggers before that code runs:
session.upload_progress.enabled = 0
post_max_size = 8M ; or 32M if the site takes uploads
upload_max_filesize = 6M ; keep it below post_max_size
; PHP 8.5 only:
fatal_error_backtraces = 0Restart PHP after changing them. If the site does not need form uploads on public URLs, blocking multipart requests at the web server or CDN for those paths removes the most direct route in. Do not limit memory with RLIMIT_AS or RLIMIT_DATA: the advisory warns that those make the vulnerable path easier to reach.
Signs you may already be compromised
- PHP files you did not add, especially in wp-content/uploads (which should contain no PHP) or with recent modification dates in core folders.
- Administrator accounts you do not recognise, or unexpected changes to wp-config.php or .htaccess.
- Outgoing connections or CPU use you cannot explain, and new cron entries for the web user.
- PHP worker crashes (segfaults) in the error log around 21–30 October, which can accompany exploitation attempts.
A server where remote code ran cannot be trusted by cleaning a few files. Restore from a backup taken before the compromise onto an updated server, and rotate every password, database credential and API key the site held.
