How to Patch WordPress CVE-2026-119977 Safely: Block the Upgrade Folder, Update, Then Hunt
The uncomfortable thing about CVE-2026-119977 is when it happens. This WordPress core bug is not reached through a plugin or a login form. It is reached while the site is applying a core update. So the update you need to make, if you let it run the normal way, opens the window one last time. This guide shows how to patch WordPress CVE-2026-119977 safely: block the staging path first, then update, then clean up and hunt. Each step takes a few minutes per site, and every step can be scripted across a fleet.
What the bug is, in one paragraph
When WordPress applies a full-package core update, it unpacks the new release into a working folder under wp-content/upgrade/. That folder sits inside the web root, and before the fix its name was predictable. The release package includes the installer, wp-admin/setup-config.php. That script only refuses to run when a wp-config.php file is present, and release packages ship without one. An attacker who polls the staging path during the unpack window can reach a working installer, point it at a database they control, and get PHP code execution on your server. Wordfence lists four conditions: a full-package update, public web and PHP access to wp-content/upgrade/, a predictable or discovered staging path, and enough time before cleanup.
WordPress fixed it in 7.1.4, released 28 October 2026, as one of 22 issues in that release (“race condition during core updates that could lead to remote code execution”, credited to Umut Bayram). The fix adds 16 random characters to the working folder name, keeps an index.php in the upgrade folder, and stops wp-config.php being copied out of the working directory during a core update. It carries CVSS 8.1 and the advisory is GHSA-4w3m-c66w-69mg.
Why this one needs a different patch routine
Attackers moved quickly. Wordfence saw the first matching request nine minutes after it deployed its firewall rule on 28 October, and logged more than 18,500 requests for staged setup-config.php paths in the first 21 hours. Some sources polled small groups of sites for about 14.5 hours, waiting for an update to start. The Hacker News reported nearly 63,000 blocked attempts in 24 hours. CISA has since added the CVE to its Known Exploited Vulnerabilities catalogue, as reported on 3 November. No confirmed compromise had been published at the time of writing. These figures count attempts, not breaches.
The detail that changes the routine is this: the update to 7.1.4 is unpacked by the old, vulnerable code. The randomised folder name only protects later updates. If automatic updates are on, many sites have already gone through that last vulnerable update without anyone choosing when. So we do things in a different order: close the path first, then update.
Step 1 — Block wp-content/upgrade/ at the web server
Put the rule in the server or virtual-host config, or in the .htaccess at the site root. Do not put it in a file inside the upgrade folder. The updater manages the contents of that folder, and a rule there may not survive the update.
nginx (inside the server block, above any PHP location):
location ^~ /wp-content/upgrade/ {
return 403;
}
The ^~ modifier matters. It stops nginx from also checking regex locations, so a location ~ \.php$ block cannot hand the request to PHP-FPM.
Apache (vhost config or site-root .htaccess, needs mod_alias):
RedirectMatch 403 ^/wp-content/upgrade/
If WordPress runs in a subdirectory, add that prefix to the path. Then test from outside:
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/wp-content/upgrade/
# expect 403
The updater writes to this folder through the filesystem, not over HTTP, so the block does not break updates. Leave it in place for good. Nothing legitimate needs to fetch files from that folder over the web.
Step 2 — Update, then confirm the version
Update to 7.1.4, or to the fixed release on your branch: 7.0.8, 6.9.11, 6.8.12, 6.7.11, 6.6.11, 6.5.14, 6.4.14, 6.3.14, 6.2.15, 6.1.16, 6.0.18, 5.9.20, 5.8.19, 5.7.21, 5.6.23, 5.5.24, 5.4.25, 5.3.27, 5.2.30, 5.1.28, 5.0.31, 4.9.35, 4.8.34 or 4.7.39. Version 4.6 and earlier get no security updates. Those sites need a migration plan, not a patch.
Don’t assume the update finished. Wordfence advises checking each site directly. With WP-CLI:
wp core version
wp core verify-checksums
verify-checksums compares core files against the official release. It flags modified core files and unexpected files in core directories, which is useful for the next step too.
Step 3 — Clean up the staging tree
After the update, nothing should be left in wp-content/upgrade/ apart from index.php. List any PHP files that are left:
find wp-content/upgrade -type f -name '*.php' ! -name 'index.php' -ls
On a site that updated cleanly, this returns nothing. If it does return files, don’t delete them yet. Copy them somewhere safe for investigation, then remove them.
Step 4 — Hunt: was the window used?
Check every site that ran a core update before the block was in place. Attackers may encode the path, so decode URLs before you match. For nginx logs:
zcat -f /var/log/nginx/access.log* | python3 -c '
import sys, urllib.parse
for line in sys.stdin:
d = urllib.parse.unquote(line).lower()
if "/wp-content/upgrade/" in d and ".php" in d:
print(line, end="")
'
Look closely at any of these requests that got a 200 response. A string of 404s from one IP is polling. A 200 on setup-config.php means the installer answered.
Then check for the things a successful attacker leaves behind:
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
wp plugin list --fields=name,status,version
wp config get DB_HOST # should match your real database host
ls -la --time-style=full-iso wp-config.php
Look for administrators you don’t recognise, plugins nobody installed, a DB_HOST you don’t expect, and a wp-config.php modified during an update window. Before 7.1.4, a malicious config written during the race could persist to the site root, so that file deserves a careful read.
Why cloud teams should care
WordPress in the cloud is everywhere: marketplace images on EC2, Lightsail and Compute Engine, containers behind load balancers, and “temporary” marketing sites that never got switched off. Automatic core updates are on by default. That’s usually a good thing, but here it meant thousands of sites ran the vulnerable update on their own schedule. A web-tier foothold rarely stays there. From a compromised instance, the next step is usually the instance metadata service and the IAM role attached to the VM. We covered the same web-tier-to-host progression in our PHP2Shell and Fragnesia analysis. The bug is different, but the lesson is the same: what the host can reach matters as much as the CVE.
The CloudShieldSecure perspective
Most teams take longer to answer “where are we running WordPress?” than to apply the patch. CloudShieldSecure’s workload inventory finds the WordPress hosts and containers across your cloud accounts, with their version and branch. That includes the long tail: sites with automatic updates turned off, sites on unsupported branches, and sites run by a team outside your normal patch process. It also flags web-tier instances whose attached roles allow more than a CMS needs, such as broad S3 access or permission to create other resources. Those roles decide how far a compromise of one blog server can spread. The point isn’t a faster patch. It’s knowing, before the next core bug, which sites you would have to patch and how much each of them could expose.
Recommended actions
- Today: add the
wp-content/upgrade/deny rule to every WordPress site’s web server config, and confirm it with a 403 test from outside. - Update to 7.1.4 or your branch’s fixed release, then confirm it with
wp core versionandwp core verify-checksums. - Clean up leftover PHP files in the staging tree, keeping copies of anything unexpected.
- Hunt access logs for decoded requests to PHP under
wp-content/upgrade/. Prioritise 200 responses, then review administrators, plugins andwp-config.php. - Find the long tail: sites with automatic updates off, sites on 4.6 or earlier, and sites outside your patch tooling.
- Reduce the blast radius: check the cloud roles attached to WordPress hosts and cut them back to what the site needs.
- Don’t rely only on a PHP-level firewall. A WAF rule helps, but it doesn’t replace the update or the web-server block.
Sources & references
- WordPress.org — Version 7.1.4 release notes and branch backports
- Rescana — WordPress Core 7.1.4 upgrade staging race RCE (GHSA-4w3m-c66w-69mg version table, Wordfence and Patchstack fix details)
- The Hacker News — WordPress RCE flaw draws nearly 63,000 attacks
- The Hacker News — CISA confirms hackers exploiting WordPress flaw
- GitHub Security Advisory GHSA-4w3m-c66w-69mg / CVE-2026-119977
Published by CSS Daily, the threat-intelligence and education hub from CloudKonsult, the team behind CloudShieldSecure.
Assess your security posture today
CloudShield Secure scans, validates, and prioritises threats across your entire attack surface.
Explore CloudShield Secure →