On 17 July 2026, WordPress shipped an emergency patch for two flaws sitting in its own core code — not a plugin, not a theme. Chained together, they let an anonymous HTTP request execute code on the server. The pair is called wp2shell. Three days later, on 20 July, several security firms confirmed it is being exploited in the wild. This piece reconstructs the timeline, explains how the two-CVE chain works, spells out who is affected, and gives the checklist to run within 24 hours.
Quick summary
- The bug is in WordPress CORE. A bare install with no plugins and no third-party themes is still exploitable, per the team that found it. "But I never installed anything sketchy" does not protect you here.
- Two CVEs, one chain.
CVE-2026-63030(REST API batch endpoint route confusion) +CVE-2026-60137(SQL injection in core) → remote code execution with no account and no user interaction. - Affected: WordPress 6.9.0–6.9.4 and 7.0.0–7.0.1. Fixed: 6.9.5 and 7.0.2 (7.1 branch: beta2). The 6.8 branch is hit by the SQL injection only, fixed in 6.8.6.
- Real attacks are happening. On 20 July, Patchstack, Hexastrike and watchTowr all reported in-the-wild exploitation — even though on 17 July Rapid7 still recorded no publicly confirmed exploitation.
- WordPress enabled forced updates through its auto-update system, but you still have to verify each site: it is unclear whether the push reaches sites that turned auto-updates off.
Key facts (sourced)
- Both CVEs were published to NVD at 17 July 2026, 20:17 UTC:
CVE-2026-63030(batch-route confusion) andCVE-2026-60137(SQL injection in theauthor__not_inparameter ofWP_Query) — NVD API, retrieved 21 Jul 2026. - The official advisory GHSA-ff9f-jf42-662q is rated Critical and lists affected versions 6.9.0–6.9.4 and 7.0.0–7.0.1, patched in 6.9.5 and 7.0.2 — GitHub Security Advisory, 17 Jul 2026.
- CVSS scores disagree between scoring parties: 63030 = 9.8 Critical (WPScan, the CNA) versus 7.5 High (CISA-ADP); 60137 = 5.9 Medium (WPScan) versus 9.1 Critical (CISA-ADP) — NVD.
- Searchlight Cyber estimates over 500 million websites run WordPress — that is the total install base, NOT the exposed set. TechCrunch cites WordPress' official statistics showing more than 400 million sites on affected versions (a figure that likely does not yet reflect recently patched sites). Separately: consultant Daniel Card sampled ~3,500 sites and estimates under 15% are actually still vulnerable; TechCrunch applies that projection across the total population of WordPress websites on the internet, which puts the figure at around 90 million — so 90 million is not 15% of 400 million — Searchlight Cyber 17 Jul; TechCrunch 20 Jul.
- The CISA KEV catalog downloaded on 21 July 2026 (catalogVersion 2026.07.16, 1,647 entries) does not yet list either CVE — CISA KEV JSON feed.
What actually happened?
On 17 July 2026 WordPress released version 7.0.2 to address one critical and one high severity issue, telling site owners to update immediately. The release note, signed by John Blackbourn, states plainly that because of the severity the WordPress.org team enabled forced updates through the auto-update system for sites on affected versions.
The flaws were found by Searchlight Cyber through its Assetnote research arm. In a post published the same day, researcher Adam Kues described a pre-authentication remote code execution flaw in WordPress core and stressed that the attack has no preconditions — an anonymous user can exploit it against a stock WordPress install with no plugins. The team deliberately withheld technical details to give defenders time to patch, releasing only a public checker at wp2shell.com.
That pause did not last. Within a day, other researchers reconstructed the full mechanism from the patch itself — WordPress is open source and the release names the files it changed — and a working proof-of-concept appeared publicly on GitHub. By 20 July, TechCrunch and SecurityWeek were both reporting active exploitation.
| When | What happened | Source |
|---|---|---|
| 17 Jul | WordPress ships 7.0.2, 6.9.5, 6.8.6 and 7.1 beta2; forced updates enabled via auto-update | WordPress.org News |
| 17 Jul, 20:17 UTC | Both CVEs published on NVD; GitHub Security Advisory GHSA-ff9f-jf42-662q rated Critical | NVD · GitHub |
| 17 Jul | Searchlight Cyber publishes the wp2shell name without technical detail; opens the wp2shell.com checker | Searchlight Cyber |
| 17 Jul | Rapid7 publishes its analysis: at the time of publication, it is not aware of any publicly confirmed in-the-wild exploitation. The same post separately notes that as of 5:45 PM Eastern, Searchlight Cyber had not published technical exploit details | Rapid7 Labs |
| 18 Jul | Full mechanism published; a working PoC goes up on GitHub. Still no exploitation reported | The Hacker News |
| Weekend 18–19 Jul | Hexastrike sees exploitation attempts in its honeypots; on Sunday it reports assisting incident response in several attacks | SecurityWeek |
| 20 Jul | Patchstack, Hexastrike and watchTowr confirm in-the-wild exploitation; Rapid7 ships checks for InsightVM/Nexpose | SecurityWeek · TechCrunch · Rapid7 |
Read in order, the table delivers the lesson: the gap between "patched" and "under attack" was three days. Speaking to SecurityWeek, watchTowr CEO Benjamin Harris noted that PoCs appeared within hours of disclosure where historically that would have taken a day or more, and argued the window between disclosure and exploitation has collapsed.
How does the two-CVE chain work?
wp2shell is not one bug but two small mistakes stacked: a SQL injection locked behind authentication, and a routing confusion that hands that lock to anonymous callers. Separately, each is hard to abuse. Together they turn an unauthenticated HTTP request into code execution on the server.
Piece one — the SQL injection (CVE-2026-60137). Per the official NVD description, WordPress does not properly sanitise the author__not_in parameter of WP_Query, which could allow SQL injection when a plugin or theme passes untrusted input into it. In essence, a parameter expected to receive an array skips its check when handed a string instead.
Piece two — batch endpoint route confusion (CVE-2026-63030). Also per NVD, WordPress 6.9.x before 6.9.5 and 7.0.x before 7.0.2 carry a REST API batch endpoint route confusion issue which, combined with the SQL injection above, could let an attacker perform SQL injection and achieve remote code execution. The batch endpoint bundles several sub-requests into one call to /wp-json/batch/v1. As The Hacker News describes the mechanism, sub-requests are tracked in two parallel arrays; an error in one sub-request knocks those arrays out of step by one, so a request ends up running under a different request's handler and slips past the endpoint's allow-list.
The operational takeaway: this lives in core code. You did not have to install anything to inherit it.
There is one narrowing condition, and it needs to be read carefully: the code-execution path only works when the site is not running a persistent object cache. That detail comes from Cloudflare and is relayed by both Rapid7 and The Hacker News. The catch is that a default WordPress install has no such cache, so default-install exposure stands. If your site runs Redis or Memcached as a persistent object cache you may sit outside this particular path — but that is a side effect, not a fix, and it does nothing for the SQL injection.
Who is affected, and who is not?
If you run WordPress 6.9.0–6.9.4 or 7.0.0–7.0.1, you are exposed to the full RCE chain. If you run 6.8.0–6.8.5, you are exposed to the SQL injection only, because the route-confusion half exists only from 6.9 onward. Anything before 6.8 is unaffected by both. Many summaries get this wrong, so the table below splits the two CVEs.
| Branch | CVE-2026-60137 (SQL injection) | CVE-2026-63030 (batch-route → RCE) | Fixed in |
|---|---|---|---|
| Before 6.8 | Not affected | Not affected | No action for these two CVEs |
| 6.8 | Affected (6.8.0–6.8.5) | Not affected | 6.8.6 |
| 6.9 | Affected | Affected (6.9.0–6.9.4) | 6.9.5 |
| 7.0 | Affected | Affected (7.0.0–7.0.1) | 7.0.2 |
| 7.1 (beta) | Affected | Affected | 7.1 beta2 |
*How to read it: "Fixed in" is the minimum version to reach on the branch you are already on — no branch jump needed, a 6.9.4 site only needs 6.9.5. Note that Searchlight Cyber's post lists "≤ 6.8.5: not affected" when describing the RCE chain, while the WordPress release note states the 6.8 branch is still affected by the SQL injection and fixed in 6.8.6. The two are not in conflict; they describe different scopes.
Why does every source quote a different CVSS score?
You will see the same flaw scored 9.8 in one place and 7.5 in another — nobody is wrong; the NVD record simply carries two independent sets of scores, one from WPScan (the CNA that assigned these CVEs) and one from CISA-ADP (CISA's authorized data publisher programme). The interesting part: the two parties rank the flaws in opposite order of severity.
| CVE | WPScan (CNA) — score & vector | CISA-ADP — score & vector |
|---|---|---|
CVE-2026-63030 (batch-route → RCE) | 9.8 — CriticalAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H | 7.5 — HighAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
CVE-2026-60137 (SQL injection) | 5.9 — MediumAV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N | 9.1 — CriticalAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
The practical consequence: if your vulnerability management tooling filters on a "≥ 9.0" threshold against a single score source, you may filter out the very CVE that matters. The vectors show where the gap on CVE-2026-60137 comes from: three of the four score sets carry AC:L (low attack complexity), but WPScan rates this one AC:H — high complexity — and counts a loss of confidentiality only (C:H/I:N/A:N), landing on 5.9; CISA-ADP rates the same flaw AC:L and adds loss of integrity (C:H/I:H/A:N), landing on 9.1. That is what separates 5.9 from 9.1 — not one party "getting it wrong".
What all four score sets actually agree on is AV:N, PR:N, UI:N: network reachable, no account and no user interaction required. That is the fact worth prioritising on, not the final number.
Worth knowing too: the CISA Known Exploited Vulnerabilities catalog we downloaded on 21 July 2026 carries catalogVersion 2026.07.16 with 1,647 entries and does not yet contain either CVE. KEV only adds a flaw once exploitation is confirmed, and the catalog updates on its own cadence — absence from KEV is not evidence of safety, especially with security firms reporting live attacks from 20 July.
What are forced updates, and why still verify?
WordPress.org enabled forced updates via the auto-update system for sites on affected versions — meaning the patch is pushed without waiting for an administrator to click anything. It is a rarely used measure and it has protected a great many sites. But it is not a guarantee, for three concrete reasons.
One: the mechanism rides the auto-update system, so sites that disabled auto-updates are an open question — The Hacker News notes WordPress has not said whether the forced push reaches them, and advises checking what you are actually running rather than assuming. Two: Rapid7 explicitly recommends that administrators verify each internet-facing site has successfully upgraded to 6.9.5, 7.0.2, or another fixed release appropriate to its branch. Three: a successful update does not erase evidence of a compromise that happened before the patch landed — if you were exposed between 17 and 20 July, patching is not the end of the job.
On the positive side, the layers above have moved too. Cloudflare rolled out WAF rules to detect and block the chain for sites behind it. On the hosting side, an Automattic spokesperson told TechCrunch that all sites the company hosts — including WordPress.com, Pressable, WPVIP and WP.cloud partners — were protected even before the release, and that the code updates were deployed immediately once published. If you use managed hosting, the first question to ask is simply: which version is my site on, and since when?
What to do within 24 hours
Job one, inside the first hour, is to open the admin dashboard of every WordPress site you own and read the actual version number — do not ask around, do not assume the host handled it. If it is below 6.9.5 / 7.0.2 / 6.8.6 for your branch, update now. The table below orders the work by urgency, compiled from the recommendations of WordPress.org, Searchlight Cyber and Rapid7.
| Window | Action | Why |
|---|---|---|
| Within 1 hour | Inventory EVERY WordPress site you run (secondary sites, landing pages, old blogs, internet-facing staging) and record each one's real version | A forgotten site is an unpatched site; attackers scan ranges, not just your main domain |
| Within 1 hour | Update to 6.9.5 / 7.0.2 (or 6.8.6 on the 6.8 branch) via Dashboard › Updates › Update Now, or download the release from WordPress.org | WordPress advises updating immediately; this is the only complete remediation |
| Within 4 hours | If you cannot update yet: block anonymous access to the batch API — block both /wp-json/batch/v1 and ?rest_route=/batch/v1 at the WAF, or install a plugin that blocks anonymous REST API access | Straight from Searchlight Cyber's mitigation guidance. Both paths must go: blocking only /wp-json leaves the query-string route open |
| Within 4 hours | Ask your host which version your site is on and when it landed. If you sit behind a CDN/WAF, confirm the blocking rules are active | Cloudflare shipped WAF rules; Automattic says sites it hosts were protected before the release |
| Within 24 hours | Review access logs for requests to batch/v1 between 17 and 20 July; check for new admin users, unfamiliar PHP files under wp-content, and unexpected scheduled tasks | Patching closes the door; it does not remove traces of anyone already inside |
| Within 24 hours | After patching: rotate admin passwords, security salts/keys, and any API credentials the site holds | If code ran on the box, treat every secret stored on it as exposed |
| This week | Re-enable auto-updates for security releases; put a WordPress version check on a recurring schedule instead of waiting for news | This round gave three days from patch to attack — a manual process does not move that fast |
*A caveat on the stopgaps: Searchlight Cyber warns that blocking the REST API or the batch endpoint may break legitimate use of the site and should be treated as an emergency temporary measure only, until you can update. Rapid7 advises against relying on workarounds instead of the patch.
A note for business leaders: this incident shows that the risk is not in what you installed, but in how fast you update. A marketing website that looks like it has "nothing to lose" is still a server that can run code, usually sharing infrastructure, mail accounts and API keys with something that matters. If your organisation is building more sensitive internal systems — for instance an internal AI stack handling company documents — patching discipline on the "minor" assets is the first line of defence.
wp2shell is a flaw in WordPress core, so a bare install with no plugins is still exploitable: if you are running WordPress 6.9.0–6.9.4 or 7.0.0–7.0.1, open your admin dashboard, check the version yourself and update to 6.9.5 or 7.0.2 today rather than waiting for the forced update to do it for you.
Frequently asked questions
My site has no unusual plugins — can it still be hit by wp2shell?
Possibly. The flaw is in WordPress core, not in a plugin or theme. Searchlight Cyber, which found it, states that the attack has no preconditions and can be exploited by an anonymous user against a stock WordPress install with no plugins. What decides your exposure is the version number: 6.9.0–6.9.4 and 7.0.0–7.0.1 carry the full RCE chain.
Which version should I update to?
The fixed release on your current branch: 6.9 → 6.9.5; 7.0 → 7.0.2; 6.8 (SQL injection only) → 6.8.6; the 7.1 beta branch → 7.1 beta2. Anything before 6.8 is unaffected by these two CVEs. Update via Dashboard › Updates › Update Now, or download the release from WordPress.org.
WordPress enabled forced updates — is there anything left for me to do?
Yes — verify it yourself. The forced push rides the auto-update system, so sites with auto-updates disabled are an open question; The Hacker News notes WordPress has not said whether the push reaches them. Rapid7 also recommends administrators check that each internet-facing site actually reached a fixed release. And patching does not erase traces of a compromise that already happened.
If I cannot update right now, how do I block this temporarily?
Per Searchlight Cyber's mitigation guidance: block anonymous access to the batch API by blocking both /wp-json/batch/v1 and ?rest_route=/batch/v1 at the WAF layer, or install a plugin that blocks anonymous REST API access entirely. The same team warns these steps may break legitimate integrations and should be temporary only, until you can update.
Does running Redis or Memcached make me immune?
Do not read it that way. Cloudflare reports the code-execution path is only reachable when the site is not running a persistent object cache, so a site with Redis or Memcached as its object cache may sit outside that specific path. But this is a configuration side effect, not a fix, and it does not cover the CVE-2026-60137 SQL injection. A default WordPress install has no such cache.
Review the security of your web infrastructure
Namtech helps businesses inventory every website they run, verify versions and patch levels, and build a recurring update routine so you are not chasing each new headline.
Book a free consultationNote: This article compiles publicly available information as of 21 July 2026 and reflects the situation at that time — this is a developing story and details may change. Figures estimating the scale of impact are third-party estimates, with their source and scope stated. CVSS scores and KEV catalog status are snapshots taken at retrieval time. This is general information, not a substitute for the assessment of the security team responsible for your systems, and not legal advice.
- WordPress.org News — "WordPress 7.0.2 Release" (17 Jul 2026): one critical and one high severity issue, forced updates enabled, backports 6.9.5 / 6.8.6 / 7.1 beta2
- Searchlight Cyber (Assetnote) — "wp2shell: Pre Authentication RCE in WordPress Core", Adam Kues (17 Jul 2026): version ranges, the 500-million estimate, mitigation guidance
- GitHub Security Advisory GHSA-ff9f-jf42-662q (17 Jul 2026): Critical, affects 6.9.0–6.9.4 and 7.0.0–7.0.1, patched in 6.9.5 / 7.0.2
- NVD — CVE-2026-63030 (published 17 Jul 2026): batch endpoint route confusion; CVSS 9.8 (WPScan) and 7.5 (CISA-ADP)
- NVD — CVE-2026-60137 (published 17 Jul 2026): SQL injection in the WP_Query author__not_in parameter; CVSS 5.9 (WPScan) and 9.1 (CISA-ADP)
- Rapid7 Labs — "CVE-2026-63030: wp2shell…" (17 Jul 2026, updated 20 Jul): persistent object cache condition, patching guidance, checks released 20 Jul
- The Hacker News — "New wp2shell WordPress Core Flaw…" (updated 18 Jul 2026): the array-desync mechanism, public PoC, KEV status
- SecurityWeek — "WP2Shell WordPress Vulnerabilities Exploited in the Wild" (20 Jul 2026): in-the-wild exploitation confirmed by Patchstack, Hexastrike, watchTowr
- TechCrunch — "Hackers are exploiting recently patched WordPress bugs…" (20 Jul 2026): 400M+ sites on affected versions, the under-15% estimate, Automattic's response
- CISA — Known Exploited Vulnerabilities Catalog (downloaded 21 Jul 2026, catalogVersion 2026.07.16, 1,647 entries): neither CVE listed