Yaamlabs

Vulnerabilities

WordPress 7.1.4: the updater race that can run code

WordPress 7.1.4 fixes a race in the core updater (CVE-2026-119977) that needs no login. How it works, what to block before updating and what to check.

WordPress 7.1.4 came out on October 28 as a security release. Its most serious fix is a race condition in the core update process, reported by Umut Bayram, that lets an attacker with no account run code on the server while the site is updating itself. Wordfence assigned it CVE-2026-119977 with a CVSS score of 8.1. Every self-hosted site from 4.7.0 through 7.1.3 is affected.

Within a day of the release, Wordfence reported more than 18,500 requests aimed at the vulnerable paths. It has not reported a successful compromise. The awkward part is that the attack window is the update itself, so the order in which you block and update matters.

How the race works

When WordPress installs a complete release package, it unpacks the new files into a working folder under wp-content/upgrade/ and copies them into place from there. WordPress's own advisory (GHSA-4w3m-c66w-69mg) says that folder had a predictable name and sat inside a directory the web server will serve. Patchstack and the German site Dr. Web, both working from a comparison of the 7.1.3 and 7.1.4 code, add that the name was derived from the package name and that cleanup removed the index.php that normally stops directory listing.

For a few seconds, then, a complete copy of WordPress sits at a guessable web address. Patchstack says that copy includes wp-admin/setup-config.php, the installer that writes a site's configuration, and that it runs without the live site's settings. An attacker who requests it in time can point it at a database they control. Wordfence's description refers to the same staged installer.

Dr. Web found the second half of the chain: the updater also copied a wp-config.php out of the working folder into the site. Wordfence describes the fix as blocking "unsafe promotion of staged configuration data". Our reading, combining the two, is that a config file planted by the staged installer could become the live site's config and run on every page load. WordPress.org has not published that chain itself.

WordPress 7.1.4 appends 16 random characters to the working folder name, recreates index.php instead of deleting it, and no longer copies wp-config.php out. The last change is not mentioned in the release notes.

Severity ratings differ. Wordfence scores it 8.1 (High) with high attack complexity, because the attacker has to win a race that lasted seconds in its lab. WordPress rates its own advisory Low. Patchstack also marked the complexity high and said it would not call the flaw practical to exploit.

What attackers are doing

Wordfence deployed a firewall rule for paying customers on October 28 and saw the first matching request nine minutes later. In the first 21 hours it counted more than 18,500 requests for staged setup-config.php paths. The two largest sources polled small groups of sites for about 14.5 hours, which fits someone waiting for an update to start. Not every request used the exact vulnerable path.

The 24-hour figures in the press vary. Techaeris, citing The Hacker News, reported 62,969 blocked attempts; Brandefense recorded 60,471 on October 31 and notes that Wordfence's counter is rolling, so each outlet read it at a different moment. SecurityOnline described the flaw as exploited in the wild. Wordfence's own figures are blocked attempts, and no compromise has been confirmed.

Two details matter for defence. The exploit requests the staged PHP file directly, so WordPress never loads and a security plugin running inside WordPress cannot see or stop it. Wordfence free users also get the rule only on November 27, after the usual 30-day delay.

What to do

1. Block web access to the upgrade folder first. This is a mitigation, not a fix. WordPress writes to wp-content/upgrade/ through the filesystem, so nothing legitimate needs to reach it over HTTP. On Nginx, add this to the server block; the ^~ prefix makes it win over the usual PHP location:

location ^~ /wp-content/upgrade/ {
    deny all;
}

On Apache, put RedirectMatch 403 ^/wp-content/upgrade/ in the .htaccess at the site root, or in the virtual host, never inside the upgrade folder. Adjust the path if WordPress lives in a subdirectory. Then request https://your-site/wp-content/upgrade/ and confirm a 403. Patchstack and Wordfence both recommend denying this path; check their current guidance before relying on our exact syntax. Doing this before you update means the update you trigger cannot be raced.

2. Update and confirm. Dashboard, then Updates, shows the installed version. With WP-CLI, wp core version shows it and wp core update installs 7.1.4; on an older branch use wp core update --minor. Fixed releases include 7.0.8, 6.9.11, 6.8.12, 6.7.11, 6.6.11, 6.5.14 and 6.4.14, down to 4.7.39 for the oldest branch. Only 7.1 is actively supported, and 4.6 or older gets no fix. Run wp core verify-checksums afterwards.

WordPress first said the backports would ship "as they become ready", and Dr. Web noted on release day that branches 6.5 and older were still pending. The version page now lists a fixed release for every branch back to 4.7.

3. Make sure future minor releases install themselves. On Dashboard, then Updates, the page should say the site is automatically kept up to date with maintenance and security releases. wp config get WP_AUTO_UPDATE_CORE should return minor or true; an error saying the constant is not defined means the default, which also installs minor releases. AUTOMATIC_UPDATER_DISABLED set to true turns every background update off.

4. Check whether a past update was raced. Because the request bypasses WordPress, only the web server log will show it:

zgrep -E "/wp-content/upgrade/.*\.php" /var/log/nginx/access.log*

A 200 response there, near the time of a core update, needs investigating. Then:

  • ls -la wp-content/upgrade/ should be empty apart from index.php once an update has finished.
  • wp user list --role=administrator --fields=ID,user_login,user_registered lists admins; question any you do not recognise.
  • find wp-content/uploads -type f -name "*.php" should return nothing on most sites.
  • Compare wp config get DB_HOST with your real database host, and check the modification time of wp-config.php against your update history.

If any of these turn up something, treat the server as compromised: restore from a backup taken before the suspicious update, then rotate the database password, the salts in wp-config.php and every administrator password.

The rest of the release

The version page counts 22 vulnerabilities across 17 advisories, plus a refresh of the bundled root certificates after the eMudhra revocation. The announcement groups them into 12 items and Pantheon's notes list 13, so counts differ by outlet. Most are stored cross-site scripting (XSS) flaws that need a Contributor account or higher, many of them in the Interactivity API. One lets unauthenticated visitors see unpublished Customizer changes. Sites with many outside authors should review who still holds those accounts.

We harden WordPress hosting and web server rules as part of safeguarding and hardening, and build and maintain sites through web application development. If you want a second pair of eyes on your update setup or your access logs, open the chat and Yaali, our AI agent, will pass your question to an engineer.


Sources: WordPress 7.1.4 announcement, WordPress version 7.1.4 page, WordPress advisory GHSA-4w3m-c66w-69mg, CVE-2026-119977 record, Wordfence, Patchstack, Dr. Web, Rescana, Brandefense, Techaeris, Search Engine Journal, Pantheon release notes, xCloud.

Back to the blog, or read this post on the full site.