wp2shell: WordPress Core Pre-Auth RCE (CVE-2026-63030 / CVE-2026-60137) — Patch Now
wp2shell chains a REST batch bug and a WP_Query SQLi into unauthenticated RCE in WordPress core. Affected versions, patches, and what to check today.
wp2shell chains CVE-2026-63030 (a REST API batch-route confusion bug in WP_REST_Server::serve_batch_request_v1(), introduced in WordPress 6.9) with CVE-2026-60137 (a SQL injection in WP_Query's author__not_in parameter, present since 6.8) into unauthenticated remote code execution. Fixed in 6.8.6, 6.9.5, and 7.0.2, released July 17, 2026. In-the-wild exploitation confirmed July 18-20. This is WordPress core, not a plugin — every unpatched site is affected regardless of what's installed on top.
If your WordPress core version starts with 6.8, 6.9, or 7.0 and you haven't updated since July 17, stop and check it before reading further. wp2shell isn't a plugin vulnerability you can shrug off if you don't run the affected plugin — it's in WordPress core itself, which means every site on an unpatched version is exposed regardless of what's installed on top of it.
TL;DR
- What: Two chained WordPress core vulnerabilities — a REST API batch-route confusion bug and a SQL injection — that together allow unauthenticated remote code execution.
- CVEs: CVE-2026-63030 (REST batch-route confusion,
WP_REST_Server::serve_batch_request_v1()) and CVE-2026-60137 (SQL injection inWP_Query'sauthor__not_inparameter). - Affected: 6.8.0–6.8.5, 6.9.0–6.9.4, 7.0.0–7.0.1. The REST bug only exists from 6.9 onward; the SQLi has been present since 6.8.
- Patched: 6.8.6, 6.9.5, 7.0.2 — released July 17, 2026.
- Exploitation status: Confirmed active in the wild July 18–20, 2026. PoC exploit code is circulating publicly.
- Do today: Check your running core version on every site you touch. Update anything below the patched line immediately — this is not a "schedule it for next maintenance window" CVE.
What wp2shell actually is
Researchers are calling this one wp2shell because successful exploitation ends with an attacker able to drop a web shell — full code execution — on an unauthenticated WordPress site. It gets there by chaining two separate bugs rather than one clean vulnerability, which is worth understanding because it explains why the fix touches two different subsystems.
CVE-2026-63030 lives in WP_REST_Server::serve_batch_request_v1(), the code that handles batched REST API requests (multiple API calls bundled into a single HTTP request, a feature introduced to cut down on round-trips). It's a route-confusion flaw: request routing inside a batch can be manipulated so a request meant for one endpoint gets dispatched with the permissions or context of another. This bug was introduced in WordPress 6.9 alongside the batch-request feature itself — it doesn't exist on 6.8.x.
CVE-2026-60137 is a more conventional SQL injection, in how WP_Query builds its author__not_in parameter. Attacker-controlled input reaches the query builder without proper parameterization. This one has been sitting in core since 6.8 and is exploitable on its own for data extraction, independent of the REST bug.
Chained together, an attacker uses the batch-route confusion to reach the vulnerable query path in an unauthenticated context, then uses the SQL injection to escalate from data read to code execution. Neither bug alone is as severe as the combination — which is exactly the profile that tends to sit quietly for a few weeks before someone public weaponizes it, which is roughly what happened here between disclosure on July 17 and confirmed exploitation by July 20.
Who's exposed
Every site running an affected core version, full stop — this isn't gated behind a specific plugin, theme, or configuration. If you manage more than one WordPress install, checking core versions across the whole fleet is the highest-leverage five minutes available to you today.
# Check core version on one site via WP-CLI wp core version # Across every site in a common webroot layout (adjust the glob to your setup) for d in /var/www/*/public_html; do echo "$d:" wp --path="$d" core version 2>/dev/null done
Anything reporting 6.8.0–6.8.5, 6.9.0–6.9.4, or 7.0.0–7.0.1 needs the update today. If a site reports 6.7.x or older, it's outside the vulnerable range for wp2shell specifically but is out of security-support scope generally and overdue for an update regardless.
Patch immediately
wp core update wp core version # confirm 6.8.6 / 6.9.5 / 7.0.2 or newer
No WP-CLI access? From /wp-admin/updates.php, WordPress will show a core update is available if you're below the patched version — click "Update Now." If the dashboard reports you're already "up to date" but wp core version (or the version footer in /wp-admin) shows a pre-patch number, your host may be pinning updates or running a caching layer that's serving a stale admin page — clear any object/page cache and re-check before assuming you're covered.
If you rely on a managed host's automatic core updates, confirm rather than assume — see the FAQ below. Kinsta, for instance, applies minor core releases like this automatically on the vast majority of plans, but if you've explicitly disabled auto-updates for a client site (common when someone's worried about a heavily customized theme breaking), that override means you're on your own for this one too.
If you can't update immediately
A frozen client site ahead of a launch, or a custom fork of core you need to test first, are real constraints — but this isn't a CVE where "we'll patch next week" is a defensible position given confirmed active exploitation. Two stopgaps, neither a substitute for the actual update:
- WAF rules. Cloudflare WAF, Wordfence, and most host-level WAFs (Kinsta, Cloudways, and other managed hosts run one by default) typically ship virtual-patch rule updates for high-profile core CVEs within a day or two of disclosure. Confirm your WAF's rule set has been updated since July 17 — an out-of-date rule set gives you nothing here.
- Restrict access to the REST batch endpoint (
/wp-json/*/batch/v1) at the edge — via your CDN, reverse proxy, or server config — if you don't actively rely on batched REST requests. This narrows the path to CVE-2026-63030 specifically but does nothing for the standalone SQL injection in CVE-2026-60137, so it's a partial mitigation at best, not a fix.
Checking whether you've already been hit
Given the endpoint of this chain is a web shell, the checks here are more serious than a typical data-exposure CVE — you're looking for evidence of code execution, not just a database read.
- New or modified files in
wp-content/uploads/, plugin/theme directories, or anywhere else PHP execution is possible — particularly files with generic names (wp-cache.php,class-cache.php) that don't match anything in your actual codebase. wp_usersfor administrator accounts you didn't create.- Scheduled tasks (
wp_cron) andwp_optionsfor unfamiliar cron hooks, injectedsiteurl/homevalues, or new API keys. - Server-level process and outbound connection logs, if you have access to them — a webshell that's been used tends to spawn processes or make outbound connections that a normal WordPress request never would.
- Access logs around July 17–20 for POST requests to
/wp-json/*/batch/v1from IPs you don't recognize, especially clustered or repeated patterns consistent with automated scanning.
If you find any of this, this is an incident, not routine cleanup — code execution means an attacker had the same capabilities you do on that server. Our hacked WordPress cleanup guide covers remediation, but for a confirmed RCE, also rotate every credential the site touches (database, SFTP, API keys, admin passwords) rather than just removing the shell you found — assume there may be a second one you haven't found yet.
The pattern: core RCEs move faster than plugin CVEs
Plugin vulnerabilities are common enough that most agencies have a rhythm for them. Core RCEs are rarer and get weaponized faster precisely because the addressable footprint — every WordPress site on an affected version — is so much larger than any single plugin's install base. Three days from patch release to confirmed in-the-wild exploitation is fast, but not unusual for this severity class once PoC code goes public.
The operational takeaway is the same one that applies to plugin CVEs, just with a lower tolerance for delay: know your fleet's core versions before an incident forces you to find out. WP Umbrella or equivalent fleet monitoring turns "which of my 40 client sites are still vulnerable" from a manual audit into a five-minute dashboard check. Our WordPress security hardening checklist covers the layered defenses — WAF rules, file-integrity monitoring, least-privilege database users — that reduce blast radius the next time a core CVE like this one lands.
Check your core version today, on every site you're responsible for. If it's below 6.8.6, 6.9.5, or 7.0.2, update it now — not after your next scheduled maintenance window.
Frequently Asked Questions
Which WordPress versions are affected by wp2shell?
Do I need to understand both CVEs, or is one enough to worry about?
Is wp2shell actually being exploited, or is this precautionary?
My host manages WordPress core updates for me — am I already covered?
// new_articles
Get notified when new guides drop
Practical WordPress guides from a working agency owner. No filler. Unsubscribe any time.
Was this article helpful?
Thanks for the feedback!