← Blog
WordPressCVE-2026-119977Remote Code ExecutionCISA KEV

WordPress Core RCE CVE-2026-119977: exploited upgrade-window race

WordPress Core 4.7–7.1.3: unauthenticated upgrade-window RCE (CVE-2026-119977), now in CISA KEV and exploited. Patch to 7.1.4, deny wp-content/upgrade/.

Zero Hunt Research··8 min read

Published by Zero Hunt, an autonomous AI red team on an on-premise appliance running private AI: automated penetration testing for networks and infrastructure, black-box or gray-box, with a human approving every step that matters.

CISA added CVE-2026-119977 to its Known Exploited Vulnerabilities catalog today, with a federal remediation deadline of November 6, 2026 — three days. The bug is an unauthenticated remote code execution in WordPress Core 4.7 through 7.1.3, the software behind roughly 40% of the web, and it lives in the one routine every site runs on its own: the core update. The fix shipped on October 28. The uncomfortable part is that installing the fix runs the vulnerable code one last time, so the order of your steps now matters more than the patch itself.

Developing story — first published 21:30 CET (20:30 UTC), November 3, 2026. Updated as the vendor and CISA publish more.

At a glance

CVE CVE-2026-119977
Product / affected versions WordPress Core 4.7.0–7.1.3 (per-branch; e.g. 7.1.0–7.1.3 · 7.0.0–7.0.7 · 6.9.0–6.9.10 · … · 4.7.0–4.7.38). 4.6 and earlier: no fix
Fixed in 7.1.4 (October 28, 2026); backported to 7.0.8 · 6.9.11 · 6.8.12 · 6.7.11 · 6.6.11 · 6.5.14 · 6.4.14 · … · 4.7.39
CVSS 8.1 HIGH · CVSS 3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H · scored by Wordfence (CNA); WordPress rates it Low
Exploited in the wild Yes · CISA KEV; Wordfence reports 18,500+ probes of staged installer paths in the first 21 hours
CISA KEV Added 2026-11-03; federal due date 2026-11-06 (BOD 26-04, forensic triage required)
Public PoC Mass scanning for staged setup-config.php paths observed; no exploit code named as public as of 2026-11-03
Official advisory WordPress 7.1.4 release

The WordPress Core upgrade window is the vulnerability

WordPress updates itself in the open. When a site takes a full-package core update — the kind that replaces the whole release, as opposed to the small incremental patches — it downloads the new release archive and extracts it into a working directory under wp-content/upgrade/. That folder sits inside the web root. On a large number of hosting setups it is reachable over HTTP and it will execute PHP.

The extracted tree is a complete copy of the new WordPress, and that copy includes wp-admin/setup-config.php — the installer that drives the "famous five-minute install." Crucially, setup-config.php is designed to run before a site has a valid wp-config.php. During the few seconds between extraction and cleanup, an unauthenticated visitor who knows the staging path can request that installer directly and drive it toward code execution on the server.

GET /wp-content/upgrade/core/wordpress/wp-admin/setup-config.php?step=1

No login. No nonce. The request just has to land in the window before WordPress moves the files into place and deletes the staging copy.

This is why NVD classes it as CWE-367, a time-of-check to time-of-use (TOCTOU) race condition. The upgrade routine stages and checks files at one instant; the live site promotes and uses them at another; in the gap, the staged copy is world-reachable. Before 7.1.4 the staging path was predictable — wp-content/upgrade/core/… and a handful of similar names — so attackers did not have to guess. They polled. As security vendor Rescana documents in its technical write-up, the attack has four preconditions: a full-package core update in progress, public web and PHP access to wp-content/upgrade/, a predictable or discovered staging path, and enough time before cleanup. The attack complexity is "High" — you have to catch the window — which is why Wordfence scores it 8.1 and WordPress itself rates it Low. Attackers resolved that disagreement empirically: Wordfence recorded more than 18,500 requests against staged setup-config.php paths in the first 21 hours after disclosure, and CISA's listing today makes the "exploited" call official.

The credit goes to Umut Bayram of Picus Security, whose report drove the WordPress 7.1.4 security release.

Why installing the fix re-opens the window

Here is the trap. A site still running a vulnerable version uses its existing — vulnerable — upgrade code to unpack the update to 7.1.4. So the act of updating performs one more full-package extraction into the predictable staging path, with the old behavior, while attackers are actively polling for exactly that. The patch closes the window for every future update, but the update that delivers it is itself exposed. That reorders the runbook: the web-server deny rule below is not a "can't patch now" fallback, it is step one before you click update.

What 7.1.4 changes, per Rescana's reading of the Wordfence and Patchstack analyses: the staging directory name is randomized with 16 random characters, an index guard is restored, and staged configuration is no longer promoted unsafely (wp-config.php is added to the files never copied out of the working directory).

Remediation

1. Am I affected?

Check the running version — WordPress admin shows it at the foot of the dashboard, or on the CLI:

wp core version
# or, without wp-cli:
grep "wp_version =" wp-includes/version.php

You are affected if you run any 4.7.0–7.1.3 build below your branch's fixed point release. Sites on 4.6 or earlier receive no fix and must be migrated to a supported branch. Note the ranges are per branch: 7.0.0–7.0.7 is affected even though 7.1.x exists.

2. Patch — exact fixed versions

Update to 7.1.4, or the backported security release for your branch:

Branch Fixed version
7.1 7.1.4
7.0 7.0.8
6.9 / 6.8 / 6.7 / 6.6 / 6.5 / 6.4 6.9.11 · 6.8.12 · 6.7.11 · 6.6.11 · 6.5.14 · 6.4.14
6.3 → 6.0 6.3.14 · 6.2.15 · 6.1.16 · 6.0.18
5.9 → 5.0 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 / 4.8 / 4.7 4.9.35 · 4.8.34 · 4.7.39

Most sites with automatic background updates enabled will receive the release on their own; verify afterward that the version actually moved.

3. Deny wp-content/upgrade/ first — then update

Because the update itself unpacks files into the staging path one last time, block web access to it before you patch, at the web-server or site-root level — not with a file placed inside the upgrade folder. The directory is only ever written to server-side; no legitimate visitor needs to fetch anything from it, so this rule is safe to leave in place permanently.

nginx:

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

Apache (site-root .htaccess):

RedirectMatch 403 ^/wp-content/upgrade/

If you front the site with a WAF or CDN, add an equivalent rule — block any request whose URI path contains /wp-content/upgrade/. Confirm it works: curl -I https://example.com/wp-content/upgrade/index.php must return 403.

4. Hunt for compromise

No network IOCs (IPs or hashes) have been published; the signals are behavioral. Map them to MITRE ATT&CK:

  • T1190 — Exploit Public-Facing Application. Web-server access logs for requests to PHP beneath the staged core tree — e.g. GET /wp-content/upgrade/*/wordpress/wp-admin/setup-config.php — that returned 200 or 302 rather than 403/404. (A default wp-content/upgrade/index.php returning 200 is normal; it is the installer and other PHP under the staged tree that matter.) Focus on the minutes around when a core update actually ran.
  • T1505.003 — Web Shell. PHP files under the web root you did not place there; run wp core verify-checksums to flag any modified or extra core files.
  • T1136.001 — Create Account. Unfamiliar administrators: wp user list --role=administrator. Unexpected scheduled tasks: wp cron event list. Unexpected plugins or must-use plugins.

5. Eradicate + verify

Remove any web shell or unknown PHP; reinstall core from known-good checksums (wp core download --force --version=<fixed> then re-verify). Rotate every administrator credential and regenerate the secret keys and salts in wp-config.php — a staged-installer compromise can seed persistence that survives a simple file cleanup. Then confirm the end state: the deny rule returns 403, the version is the fixed one, and wp core verify-checksums is clean.

What is not known yet

  • Whether any site has been successfully compromised (as opposed to probed). The reporting as of today describes mass scanning for staged installer paths, not confirmed shells.
  • The full population of predictable path variants attackers are polling beyond core/.
  • Whether custom or third-party updaters that bypass the core routine still extract into predictable paths under wp-content/ — a plausible residual exposure the fix to core does not reach.
  • Any ransomware or named-actor association: CISA records known ransomware use as "Unknown."

Closing the window with proof, not guesswork

The hard question this CVE poses is not "is there a patch" — there is — but "what do I do now, and in what order, so that patching doesn't become the exploitation event." That is a remediation-sequencing problem, and it is exactly where Zero Hunt's AI Remediation Advisor earns its place. The advisor ranks what to touch by real exploitability — CISA KEV first, then confirmed in-the-wild exploitation, then CVSS and EPSS — so a KEV entry with a three-day BOD 26-04 clock sorts to the top of the queue rather than competing with cosmetic findings. For each item it emits the exact fix with the rollout and rollback notes and a compensating control, which for this bug is precisely the point: deny wp-content/upgrade/ at the edge, then take the update, then lift nothing until the version and checksums verify. And because Zero Hunt is an autonomous AI red team that runs on-premise on its own private models, with a human in the loop for anything intrusive, it then re-checks the fix the same way it would prove the flaw — a gray-box, black-box-safe test against your own installed version to confirm the staged path is no longer web-reachable and the race no longer wins. Finding the exploitable window before an attacker does, and re-verifying it is shut, is the generative-pentest half of the same engine. If you also run the WordPress estate described in our earlier write-up of the wp2shell pre-auth RCE chain, treat both as the same class of problem: the update path and the request path are attack surface, and continuous validation — see automated penetration testing — is how you keep them honest. For why a three-day federal deadline now attaches to a bug like this, read our note on CISA's BOD 26-04 risk-based patching. When you want to see it run against your own sites, get in touch.

Every vulnerability CISA lists as exploited, with federal due dates: CISA KEV tracker →

Patching one CVE at a time? A CTEM program validates which exposures are actually exploitable before the next advisory: what CTEM is →

Is this exploitable in your environment?

Zero Hunt answers that on your own network: an autonomous AI red team on an on-premise appliance, running on private AI, black-box or gray-box, with a human approving every step that matters. Proof of what is exploitable, the fix, and signed evidence — no data leaves your perimeter.