Skip to content
Attack Surface Management

wp2shell (CVE-2026-63030): Unauthenticated Pre-Auth RCE in WordPress Core – Advisory + Nuclei Detection

xer0dayz · · 14 min read

On July 17, 2026, WordPress shipped an emergency round of releases – 7.0.2, 6.9.5, and 6.8.6 – to close wp2shell, tracked as CVE-2026-63030: a pre-authentication remote code execution chain in WordPress Core. Two words make this one matter: “pre-authentication” and “Core.” An anonymous attacker, with no account and no vulnerable plugin, can reach code execution on a default WordPress install. With WordPress powering a large share of the web, the exposed population is enormous, and WordPress.org took the unusual step of forcing automatic updates for affected versions.

This advisory is three things at once. First, a plain-English explanation of what wp2shell is and who is affected. Second, a ready-to-run Nuclei detection template you can copy, paste, and scan with today. Third, a walkthrough of how to find every affected WordPress instance across an attack surface with Sn1per. Credit where it is due: wp2shell was discovered by Adam Kues of Searchlight Cyber’s Assetnote research team and reported responsibly through WordPress’s HackerOne program. Their write-up is the authoritative technical source (Searchlight Cyber advisory).

wp2shell at a glance

  • CVE: CVE-2026-63030 (REST batch-route confusion) chained with CVE-2026-60137 (WP_Query SQL injection).
  • Impact: unauthenticated, pre-auth remote code execution against a stock install with zero plugins.
  • Affected: WordPress Core 6.9.0 – 6.9.4 and 7.0.0 – 7.0.1.
  • Fixed: 7.0.2, 6.9.5, and 6.8.6, all released July 17, 2026.
  • Fix now: update Core. If you cannot, block /wp-json/batch/v1 and /?rest_route=/batch/v1 at your WAF.
  • Detect: use the Nuclei template below for spot checks, or Sn1per to sweep an entire attack surface.

What is wp2shell (CVE-2026-63030)?

wp2shell is the nickname for a chain of two vulnerabilities that together turn an anonymous HTTP request into remote code execution. Neither half is catastrophic alone; combined, they are.

The first link is CVE-2026-60137, a SQL injection in the author__not_in parameter of WP_Query – the core class behind almost every database query WordPress runs. It is classified as CWE-89 (SQL injection), tracked as GHSA-fpp7-x2x2-2mjf, and reaches back to WordPress 6.8, giving it the widest exposure of the two. On its own it is reachable only by an authenticated user, because a blocklist restricts the vulnerable parameter to logged-in callers.

The second link is CVE-2026-63030 itself, a REST API batch-route confusion (CWE-436, “interpretation conflict”) in the /wp-json/batch/v1 endpoint that has shipped with Core since version 5.6 in 2020. The flaw lets a crafted request dispatch under the wrong handler, effectively bypassing the permission checks that should stop an anonymous caller. That bypass is what unblocks the authenticated-only SQL injection: route CVE-2026-60137 through the confused batch endpoint on 6.9 and later, and the confined injection becomes reachable pre-auth and escalates to full remote code execution. That escalation is the “shell” in wp2shell.

One nuance worth knowing for triage: the CVSS score for this chain is disputed across sources. The NVD entry carries both a 9.8 Critical CNA score and a separate 7.5 secondary (CISA-ADP) assessment; Wordfence and WPScan score it 9.8, while the GitHub Security Advisory lists 7.5. The published vector is CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. Do not let a single number drive your response – the operational facts (pre-auth, remote, Core, no plugin required, patch available, public partial PoC) matter more than which score you trust.

The detail that makes it a headline is the absence of preconditions. No login, no plugin, no unusual configuration – a default WordPress install with zero plugins is exploitable by an anonymous request. That is why WordPress forced auto-updates, and why every internet-facing instance needs to be checked rather than assumed patched.

One factor can blunt the worst case: per analysis from Cloudflare and the WordPress security team, the full RCE path is reachable when a persistent object cache is not enabled – a common default, but many managed hosts run Redis or Memcached, which may shield the RCE tip of the chain (the standalone SQL injection still applies). This detail was intentionally held back from the first announcement so no one used it as an excuse to delay patching.

A responsible-disclosure note on the exploit status: at the time of the fix there was no public proof-of-concept and no confirmed in-the-wild exploitation, and the researchers withheld the full exploit details to give defenders time to patch. That window is already closing. As of July 18, 2026, a public proof-of-concept demonstrates the SQL injection half (it can read the database, including administrator password hashes), the full RCE primitive has not yet been published, and early reports of in-the-wild activity have begun to surface. Because WordPress is open source, a complete exploit is widely expected to be reconstructed quickly from the patch diff, so treat the clock as running.

Affected and fixed versions

The two flaws have slightly different reach, which the version math reflects. The batch-route confusion that enables RCE only exists from 6.9.0 onward. The SQL injection alone reaches back to 6.8. Here is the practical breakdown:

WordPress version Status Action
Below 6.8.0 Not affected by either issue None for wp2shell
6.8.0 – 6.8.5 SQL injection only (CVE-2026-60137); not the RCE chain Update to 6.8.6
6.8.6 Patched None
6.9.0 – 6.9.4 Affected by wp2shell RCE Update to 6.9.5 now
6.9.5 Patched None
7.0.0 – 7.0.1 Affected by wp2shell RCE Update to 7.0.2 now
7.0.2 Patched None
7.1 beta line Carries the fix None

The key takeaway: the RCE-affected versions are 6.9.0 – 6.9.4 and 7.0.0 – 7.0.1. If wp core version returns anything in those ranges, treat the site as at-risk and patch immediately. If you are on 6.8.x you are still exposed to the standalone SQL injection and should move to 6.8.6, even though the full RCE chain does not apply to that branch.

How the exploit chain works

WordPress 5.6 added /wp-json/batch/v1 so a client can bundle several REST calls into a single request. Server-side, the batch handler validates each sub-request, builds a list of matched routes alongside a parallel list of validation results, and then dispatches each matched route. The bug is an alignment problem: when a request contains a malformed or unusual path, the matched-routes array and the validation array fall out of sync. A sub-request can then be dispatched under a handler that was validated for a different route. That is the “route confusion,” and its practical consequence is that the permission and authentication checks that should apply to an anonymous caller are effectively bypassed, because the request is handled as though it had passed a different route’s checks.

With that authentication barrier gone, the request reaches an injectable code path: the author__not_in parameter flows into WP_Query and, ultimately, into a SQL statement without safe parameterization. The result is boolean- and time-based blind SQL injection, reachable pre-authentication – already enough to read arbitrary database contents, including the administrator password hashes in wp_users. Turning database read into code execution takes one more step: either using recovered credentials, or an additional pre-authentication database-to-file-write primitive. The researchers did not publish that final primitive, which is why there is no drop-in public exploit yet.

We are deliberately not publishing a working exploit here. What follows is detection only – version fingerprinting that tells you whether a given WordPress instance sits in the affected range, so you can prioritize patching. That is the responsible half, and for defenders it is the useful half. It is the same approach we took in our earlier advisories, such as CVE-2024-21733 (Apache Tomcat request smuggling) and Spring4Shell (CVE-2022-22965): explain the flaw, then ship a safe detection you can run at scale.

Am I affected? Quick manual checks

On a host you control, the authoritative check is WP-CLI, run from the WordPress root:

# Authoritative: ask WordPress directly, from the WordPress root
wp core version
# At-risk if it prints 6.9.0-6.9.4 or 7.0.0-7.0.1.
# Fixed at 6.9.5 / 7.0.2 / 6.8.6.

From the outside, a stock install advertises its version in several public places. Any one of these is enough to fingerprint it:

# Generator meta tag on the home page
curl -s https://example.com/ | grep -i 'name="generator"'

# RSS feed generator
curl -s 'https://example.com/?feed=rss2' | grep -i 'generator'

# Core asset version on wp-includes scripts
curl -s https://example.com/ | grep -oiE '/wp-includes/[^"]*?ver=[0-9.]+' | head

One caveat that matters for accuracy: hardening plugins and some WAFs strip the generator tag, the feed generator, and asset version strings. On those sites external version detection returns nothing, which is neither a positive nor a negative – fall back to the authoritative wp core version on the host, or an authenticated dashboard check under Dashboard → Updates.

Nuclei detection template for wp2shell

To check one site or ten thousand, a version-based Nuclei template is the fastest path. The template below – the same one shipped in Sn1per’s curated template set – passively fingerprints the WordPress core version from four independent public sources (the generator meta tag, the RSS feed generator, the OPML generator, and core /wp-includes/ asset ?ver= strings) and flags any install whose version falls inside the affected 6.9.0 – 6.9.4 or 7.0.0 – 7.0.1 ranges using Nuclei’s compare_versions DSL. It sends no exploit traffic; it only reads version markers, so it is safe to run against production.

id: CVE-2026-63030

info:
  name: WordPress Core 6.9.0-6.9.4 / 7.0.0-7.0.1 - Unauthenticated RCE (wp2shell)
  author: xer0dayz
  severity: critical
  description: |
    WordPress Core is affected by "wp2shell" (CVE-2026-63030), a pre-authentication
    remote code execution chain. A REST API batch-route confusion in /wp-json/batch/v1
    (CVE-2026-63030, CWE-436) escalates an unauthenticated SQL injection in the
    WP_Query author__not_in parameter (CVE-2026-60137, CWE-89) into full remote code
    execution against a default install with zero plugins. This template passively
    fingerprints the running WordPress core version from public sources (generator
    meta tag, RSS feed generator, OPML generator, and core /wp-includes/ asset
    versions) and flags installs inside the affected ranges 6.9.0-6.9.4 and
    7.0.0-7.0.1. Fixed in 7.0.2, 6.9.5, and 6.8.6 (released 2026-07-17).
  remediation: |
    Update WordPress Core to 7.0.2 (7.0 branch), 6.9.5 (6.9 branch), or 6.8.6 (6.8 branch).
    If patching is not immediately possible, block anonymous access to BOTH
    /wp-json/batch/v1 and /?rest_route=/batch/v1 at the WAF (a rule covering only the
    path leaves the query-string route open). Verify with: wp core version.
  reference:
    - https://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/
    - https://wp2shell.com/
    - https://nvd.nist.gov/vuln/detail/CVE-2026-63030
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2026-63030
    cwe-id: CWE-436
  metadata:
    verified: true
    max-request: 4
    vendor: wordpress
    product: wordpress
    shodan-query: http.component:"WordPress"
  tags: cve,cve2026,wordpress,wp,wp2shell,rce,sqli,unauth,route-confusion

http:
  - method: GET
    path:
      - "{{BaseURL}}"
      - "{{BaseURL}}/?feed=rss2"
      - "{{BaseURL}}/feed/"
      - "{{BaseURL}}/wp-links-opml.php"

    stop-at-first-match: true
    redirects: true
    max-redirects: 2

    matchers-condition: or
    matchers:
      - type: dsl
        name: affected-6.9.0-through-6.9.4
        dsl:
          - "compare_versions(version, '>= 6.9.0', '<= 6.9.4')"

      - type: dsl
        name: affected-7.0.0-through-7.0.1
        dsl:
          - "compare_versions(version, '>= 7.0.0', '<= 7.0.1')"

    extractors:
      - type: regex
        name: version
        part: body
        group: 1
        internal: true
        regex:
          - '(?:content="WordPress |wordpress.org/?v=|generator="WordPress/|/wp-includes/[^"s>]*?ver=)([0-9]+.[0-9]+(?:.[0-9]+)?)'

      - type: regex
        name: wordpress-version
        part: body
        group: 1
        regex:
          - '(?:content="WordPress |wordpress.org/?v=|generator="WordPress/|/wp-includes/[^"s>]*?ver=)([0-9]+.[0-9]+(?:.[0-9]+)?)'

Save it as CVE-2026-63030.yaml and run it against a single target or a list of hosts:

# Single target
nuclei -t CVE-2026-63030.yaml -u https://example.com/

# A whole list of WordPress hosts
nuclei -t CVE-2026-63030.yaml -l wordpress-hosts.txt

# Example match against an affected 7.0.1 instance:
[CVE-2026-63030] [http] [critical] https://example.com/ [affected-7.0.0-through-7.0.1] [7.0.1]

The named matchers tell you which branch matched (affected-6.9.0-through-6.9.4 or affected-7.0.0-through-7.0.1) and the extracted version appears in the results, so triage is immediate. Because the check is version-based, its one blind spot is the same as the manual checks: a site that strips every version marker cannot be fingerprinted remotely. For those, and for anyone who needs defensible coverage across an entire estate, the next step up is Sn1per.

Detecting wp2shell across your attack surface with Sn1per

One template against one URL is fine for a spot check. The real problem is scale and discovery: most organizations do not have a clean list of every WordPress instance they expose. A shadow marketing microsite, a forgotten staging blog, a subsidiary’s WordPress on a recently acquired domain – those are exactly the hosts that miss the forced auto-update and quietly sit on 7.0.1 for weeks. Finding them is an attack-surface problem before it is a scanning problem.

Sn1per is built for that. It runs discovery and detection as one engine: it enumerates the surface (subdomains, live hosts, services, technologies), fingerprints what is running, and runs its curated Nuclei set – including this wp2shell template – against everything it finds, into a persistent named workspace. Instead of “scan this one URL,” the workflow becomes “discover every WordPress we expose and flag the ones on an affected version.”

# Discover the surface, then run web detections (incl. the wp2shell template)
# into a persistent workspace
sniper -t example.com -m recon -w acme-wp
sniper -t example.com -m web   -w acme-wp

# Pull the affected-version findings back out via the JSON API (Sn1per Professional 2026)
curl -sk -H "X-API-Key: $SN1PER_API_KEY" 
  "https://sn1per.local/pro/api.php?action=vulnerabilities&workspace=acme-wp" | jq '.'

Because Sn1per keeps results in workspaces, the same command from cron or a CI/CD pipeline re-checks the surface on a schedule, so a newly discovered or freshly stood-up WordPress gets fingerprinted within a run rather than at the next annual pentest – the model we cover in continuous attack surface testing and automated penetration testing. Findings also feed Sn1per’s correlation layer, so a wp2shell hit on a host that also exposes other weaknesses is ranked in context rather than as an isolated line item.

And because Sn1per is self-hosted – it has run on-prem since 2015 and is Docker-first – the entire scan, including the target list of your unpatched WordPress sites, never leaves your perimeter. For an offensive-security tool inventorying your own exposure, that on-prem posture is the point: a map of what you have not patched yet is precisely the data you do not want sitting in someone else’s cloud.

Which Sn1per edition fits

Capability Community Edition Professional 2026 Enterprise
Curated Nuclei set incl. wp2shell template Yes Yes Yes
Discovery + detection engine Yes Yes Yes
Scale Single operator Up to 150 assets, single operator Near-unlimited, multi-operator
Web UI + scheduled scans No Yes Yes
JSON API + SIEM / ticketing export No Yes Yes
Multi-workspace / multi-team No No Yes
Self-hosted / on-prem Yes Yes Yes

Sn1per Community Edition is free and open-source and ships the same detection engine, so a spot check across a handful of hosts costs nothing. Sn1per Professional 2026 adds the web UI, scheduled scans, and the JSON API for teams that want continuous coverage and findings routed into a SIEM or ticket queue; live pricing is on the shop. Sn1per Enterprise scales to near-unlimited assets with multi-operator, multi-workspace management for MSSPs and large security teams (custom quote). If you are weighing the two paid tiers, our Professional vs Enterprise comparison breaks it down.

Remediation and mitigation

1. Patch. This is the only real fix. Update Core to 7.0.2 (7.0 branch), 6.9.5 (6.9 branch), or 6.8.6 (6.8 branch). WordPress forced auto-updates for affected versions, but verify rather than assume it completed – confirm with wp core version on every internet-facing instance you own.

2. If you cannot patch immediately, block the batch endpoint at the WAF. Every temporary mitigation reduces to the same idea: keep anonymous callers off the batch endpoint. Block both routes – a rule that only covers the path leaves the query-string route open:

# Both of these must be blocked for anonymous users:
/wp-json/batch/v1
/?rest_route=/batch/v1

Options include a WAF rule blocking both routes, disabling unauthenticated REST access, or a small must-use plugin that rejects anonymous batch requests. Treat these as stopgaps: they can break legitimate REST integrations, and they are not a substitute for patching.

3. Verify integrity after patching. If a host was on an affected version and internet-exposed during the window, confirm the update landed cleanly and the core files are intact with wp core verify-checksums. Given no confirmed in-the-wild exploitation at disclosure, the risk during the short window was low, but the check is cheap.

Frequently asked questions

What is wp2shell? wp2shell is the nickname for CVE-2026-63030, a pre-authentication remote code execution chain in WordPress Core. It combines a REST API batch-route confusion (CVE-2026-63030) with a SQL injection in WP_Query (CVE-2026-60137) so that an anonymous, unauthenticated attacker can reach code execution on a default WordPress install with no plugins.

Which WordPress versions are affected? The RCE chain affects WordPress Core 6.9.0 through 6.9.4 and 7.0.0 through 7.0.1. It is fixed in 7.0.2, 6.9.5, and 6.8.6, released on July 17, 2026. WordPress 6.8.0 through 6.8.5 is exposed to the standalone SQL injection and should move to 6.8.6; versions below 6.8 are not affected by either issue.

Is there a public exploit, and is it being exploited? At disclosure there was no public proof-of-concept and no confirmed in-the-wild exploitation, and the researchers withheld the final exploit primitive. Because WordPress is open source, a working exploit is expected to be reconstructed quickly from the patch, so patching promptly is important.

How do I detect wp2shell across many sites? Use the Nuclei template in this post for a version-based check against a single host or a list. To cover an entire attack surface, including WordPress instances you may not have inventoried, use Sn1per, which discovers hosts and runs the same template into a persistent workspace on a schedule.

Is the Nuclei template safe to run in production? Yes. It only reads public version markers (the generator tag, RSS and OPML generators, and core asset version strings) and compares the version against the affected ranges. It sends no exploit traffic and does not attempt the SQL injection or the batch-route confusion, so it is safe against production targets.

wp2shell is the kind of vulnerability that punishes incomplete inventory more than slow patching: the sites that get compromised are the ones nobody remembered they had. Patch what you know about today, then use the template above – or Sn1per across your whole surface – to find the WordPress you forgot.

Written by

xer0dayz

Founder of XeroSecurity.

Try it free

See your attack surface like a pentester would.

Sn1per finds, ranks, and exploits real vulnerabilities autonomously — the same way attackers do.