Home wp2shell: a defender’s guide (CVE-2026-63030 + CVE-2026-60137) ← Return to overview wp2shell: a defender’s guide (CVE-2026-63030 + CVE-2026-60137) Jul 20, 2026 By: Eye Security wp2shell is a critical, unauthenticated remote code execution vulnerability in WordPress core shared with the public on July 17th, 2026. It requires no plugins, no theme, and no login. It was discovered and disclosed by Adam Kues of Searchlight Cyber , who published an official advisory and a live vulnerability checker at wp2shell.com . Credit for the discovery and the checker belongs entirely to their team. At Eye Security , we were among the first responders. WordPress.org forced automatic updates across its install base, and with an estimated 200-plus million live WordPress sites that push almost certainly saved a very large number of them before the exploit spread. But, it probably did not save all of them: forced updates do not reliably reach sites that disabled auto-updates, or were already compromised before the update landed. This post documents the defensive tooling and forensic methodology our team built to answer the questions a defender actually has: Am I on a patched version? Was I already hit? And if I was, where is the evidence? About wp2shell wp2shell chains two WordPress core flaws: a REST API route-confusion bug in the batch endpoint (CVE-2026-63030) and an SQL injection in WP_Query (CVE-2026-60137). Together they let an unauthenticated attacker go from no access to a rogue administrator and code execution on a default install. The full mechanics are in the section below. Why this one is different The vast majority of WordPress security issues live in plugins or themes. wp2shell is in WordPress itself, so it reaches a bare install with nothing added. It is unauthenticated, requires no user interaction, and the entry point (the REST batch endpoint) is enabled by default. The exposed population is enormous, which is exactly why WordPress.org initiated forced automatic updates. One narrowing condition is worth noting: the code-execution path depends on the site not using a persistent external object cache (such as Redis or Memcached), which changes how the underlying query is built. That reduces the blast radius for some larger deployments but does nothing for the millions of stock installs that never touch an external cache. How the exploit chain works A full, working proof-of-concept has been public on GitHub since shortly after disclosure ( Icex0/wp2shell-poc ) and we have independently verified that it executes end to end against an affected, default install. The chain : an unauthenticated route-confusion bug in the default /wp-json/batch/v1 endpoint (CVE-2026-63030) smuggles input into an author__not_in SQL injection in WP_Query (CVE-2026-60137). That gets escalated via a UNION-forged post and oEmbed cache write into a rogue administrator and a webshell plugin, taking it from pre-auth all the way to RCE. Fixed by wp_parse_id_list() in 7.0.2. Not one request, and log-blind : a full run is a dozen to dozens of requests (one value per UNION read, far more when forced into blind/error extraction). The decisive steps ride inside batch POST bodies that rarely appear in access logs, so the database artifacts are the primary evidence, not the logs. Residual evidence and caveat : the PoC self-cleans the admin and webshell but leaves the oEmbed cache rows and changeset/request posts (the basis for our Compromise Scanner below). The UNION step needs the full-row query path, so sites on a persistent external object cache (Redis/Memcached) may dodge this specific path. Patch anyway. Affected and fixed versions The two bugs do not reach the same versions, which is the key to who is exposed to what. The SQL injection reaches further back than the full RCE chain, so the ranges split. Version range Exposure Fixed in 6.8.0 – 6.8.5 SQL injection only (no RCE chain) 6.8.6 6.9.0 – 6.9.4 Full unauthenticated RCE chain 6.9.5 7.0.0 – 7.0.1 Full unauthenticated RCE chain 7.0.2 What to do right now Verify that your WordPress instance is running a patched version, do not assume your site has already been updated automatically, and monitor for unexpected activity on any WordPress infrastructure exposed to the internet. The forced auto-update rollout very likely protected you, and that is genuinely good news. We have not independently verified how broadly or reliably those updates reach environments where auto-updates are disabled or restricted, and a site that was compromised before the patch arrived stays compromised. Confirm the version in your dashboard, and if there is any doubt, run a compromise check rather than trusting that the update happened. Check your website via wp2shell.com (maintained by SearchLight Cyber) Use one or both of our free tools below: a browser extension and WordPress plugin If you genuinely cannot update immediately, the advisory lists temporary measures that all amount to keeping anonymous callers off the batch endpoint. If you think WordPress might have been exposed, and/or if you just want to be sure: reset every user password. The injection alone can read the wp_users table, which means an attacker may already hold your password hashes. Force a reset for all accounts (administrators first) and encourage users to change that password anywhere else they reused it. Our free tools We built two free tools plus a forensic methodology to help checking if you are patched and to check for signss of (active) compromise. Tool 1: wp2shell checker (browser extension) Our browser extension can be used on any WordPress site to answer three questions: is this WordPress, is it running a patched version, and is it exposed to wp2shell? Download below . While store approval is pending, you need to enable Developer Mode in Chrome, Edge or Firefox to load/unpack this extension. wp2shell-checker-1.0.0-chrome Download Disclaimer the checker reports what a WordPress site tells the outside world, so it is a fast triage aid rather than a guarantee. Version strings can be hidden or spoofed, hardened sites may not expose enough to judge confidently, and a report of “patched” does not mean a site was never compromised before it was updated. Use it to prioritise, then confirm with the compromise scanner and the checks below. We will keep the checker updated as new details and intelligence about wp2shell come to light. Tool 2: compromise scanner (WordPress plugin) The Compromise Scanner is a simple WordPress plugin that detects the artifacts this chain leaves behind. It does not mitigate; you still need to update. A weighted-indicator scan maps to a score, which maps to one of three verdicts. Each indicator carries a severity and a point value; the table below lists them. We added an export button that can be used for further (forensic) analysis. Privacy is built in: password hashes and session tokens are never exported, nothing will leave your WordPress installation. Download our WordPress extension here (pending WordPress.org approval, sourcecode here ). Disclaimer: the scanner is a first signal, not guarentee. It looks for the specific traces this attack is known to leave, so a clean result lowers your risk but does not prove a site was never touched, and a determined attacker who cleaned up thoroughly can still evade it. Treat its output as evidence to act on, not a final verdict, and combine it with manual checks. As new details and intelligence about wp2shell emerge, we will update the detection logic, so make sure you are running the latest version. Indicators of compromise The following indicators are derived from reading and testing the public proof-of-concepts. Because rogue accounts and plugin folders use a static prefix plus a random suffix, match on the prefixes rather than exact strings. Attribution to the specific PoC that introduced each indicator is noted where relevant. Type Indicator Rogue admin login wp2_* , w2s_* Rogue admin email domain @wp2shell.invalid , @wp2shell.shellcode.lol Exploit endpoint /wp-json/batch/v1 , /?rest_route=/batch/v1 Database artifacts oembed_cache loopback rows, customize_changeset with very high parent IDs, orphaned usermeta, user-ID gaps Where to look on Linux (forensics) Because the steps of the chain never seem to reach the web server access log, the database is your primary evidence and the filesystem is where the follow-on activity lands. On a typical Linux WordPress host, the following paths are the ones worth pulling for further forensic analysis. Database (primary evidence): the wp_users and wp_usermeta tables for unexpected administrator rows, and wp_options for tampered active_plugins , siteurl / home , and any injected _transient_ / object-cache entries. Dump via mysqldump from a copy, not the live DB. Web root: /var/www/html (or the site’s docroot), look for recently modified or newly created PHP files. find DOCROOT -name "*.php" -newermt "2026-07-16" -printf "%TY-%Tm-%Td %TH:%TM %p\n" is a fast first pass. Web server logs: /var/log/apache2/ or /var/log/nginx/ . The access log will show the REST batch entrypoint and any later webshell hits (source IP, timing, entrypoint) but not the injection itself. The Apache error.log can accidentally leak an injected query if a UNION threw a SQL syntax error, so check it. PHP and FPM logs: /var/log/php*-fpm.log and the error_log files PHP drops into the web root or per-directory; unexpected fatal errors or warnings around the intrusion window are useful corroboration. PHP sessions and temp: /var/lib/php/sessions/ and /tmp for dropped payloads or staging files. System and auth: /var/log/auth.log (or secure ), shell history ( ~/.bash_history for www-data and any service accounts), /etc/crontab , /etc/cron.* and per-user crontabs for persistence, and /etc/passwd for added local accounts. One caveat of this vulnerability: a clean exploit run can leave almost nothing in the logs, so the absence of log lines is not evidence of safety. Let the databas
The wp2shell exploit chain (CVE-2026-63030, CVSS 9.8 CRITICAL, and CVE-2026-60137, CVSS 5.9 MEDIUM) is a critical, pre-authentication remote code execution vulnerability in WordPress core that chains a REST API route-confusion bug with an SQL injection to achieve administrator creation and code execution on default installations. The article states the issue was fixed in WordPress 7.0.2 via the `wp_parse_id_list()` function, but it does not specify the affected version range. For defenders, the article provides forensic artifacts, a compromise scanner plugin, and a browser extension to check patch status.