wp2shell: Pre-Auth RCE Chain in WordPress Core (CVE-2026-63030 & CVE-2026-60137)

– min read

If you run WordPress, this one’s a must-read. A couple of weeks ago, a critical vulnerability chain called wp2shell dropped, and it’s the real deal — unauthenticated remote code execution on a default WordPress install. No plugins required. No special configuration. Just a vanilla WordPress site and you’re in.

What is wp2shell?

wp2shell is not a single bug — it’s a chain of two CVEs discovered by Adam Kues from Searchlight Cyber / Assetnote. Together, they turn a REST API routing quirk into a full SQL injection, then into a new admin account, and finally into a webshell on your server.

The vulnerabilities affect WordPress 6.9.0 through 6.9.4, and 7.0.0 through 7.0.1. Patched in 6.9.5 and 7.0.2.

The Two CVEs

CVE-2026-63030 — REST API Batch Route Confusion (CVSS 8.8)

WordPress ships a /wp-json/batch/v1 endpoint that processes multiple sub-requests in one go. The bug is in serve_batch_request_v1() — it builds parallel arrays for route matching and permission validation, but when a sub-request fails silently, the arrays desync. Every sub-request after that point gets paired with the wrong route’s authentication state. This lets an attacker sneak an unauthenticated request past the permission check.

CVE-2026-60137 — SQL Injection via author__not_in (CVSS 9.8)

With the route confusion bypassing auth, the attacker can reach WP_Query’s author__not_in parameter. When supplied as a scalar string (not an array), it gets interpolated directly into raw SQL. No sanitization. No parameterised query. Just straight injection into a WHERE clause.

The Attack Chain

Here’s how it works end-to-end:

  • Attacker sends a crafted POST to /wp-json/batch/v1 with a nested batch payload
  • The inner batch triggers the desync condition — the second sub-request slips through without auth
  • That sub-request hits /wp/v2/posts with a malicious author__not_in parameter
  • The parameter is injected into raw SQL, giving the attacker a read/write SQLi primitive
  • The attacker extracts admin password hashes, creates a new admin account, or writes a webshell via MySQL INTO OUTFILE
  • Full site takeover, potentially with persistent access

Why It’s Bad

This isn’t a niche plugin bug. It’s in WordPress core. Every unpatched WordPress site is a target. And since CISA added it to the Known Exploited Vulnerabilities catalog on July 21, 2026, and a public PoC hit GitHub the next day, the window for proactive patching is long gone. Mass scanning is already happening.

Detection

The 0xsha variant of the exploit includes a non-destructive check that uses a structural signal — if the batch desync causes a block_cannot_read error from the block-renderer’s permission callback on a POST request, you’re vulnerable. No data is modified, no rows touched.

Remediation

  • Update to WordPress 6.9.5 or 7.0.2 immediately
  • Don’t rely on automatic background updates — verify explicitly
  • Check for unexpected admin accounts or suspicious files in wp-content/uploads/
  • Review wp-config.php for DISALLOW_FILE_EDIT and DISALLOW_FILE_MOD
  • If you suspect compromise, rotate all credentials and audit user registrations

PoC & References

Links to the public PoC and the best technical writeups I’ve found:

Patch now. Don’t wait. If you’re running WordPress, assume you’re being scanned right now.

Mohamad ZulfahmyCybersecurity · OffSec · Entrepreneur
About me ↗
ON THIS PAGE
On this page