Fenrir SOCFenrir MDRGARM · gratisFenrir WP BridgeFenrir WP Central How it works Pricing Compliance Blog
← Blog

2026-07-28 · Team Fenrir

wp2shell: how to check if your WordPress is exposed

wp2shell is the name given to a chain of two WordPress vulnerabilities — CVE-2026-63030 and CVE-2026-60137 — that together allow remote code execution without authentication, on a default WordPress install with no plugins. Fixes have been available since 17 July 2026. Exploitation in the wild is confirmed. Only one operational question matters: is your version on the list? That takes one command to answer.

What is wp2shell, in two lines?

It is not one bug: it is two, and they only matter when lined up.

  • CVE-2026-63030 — a route confusion issue on the REST batch endpoint. NVD describes it as a flaw which, “combined with the author__not_in WP_Query SQL Injection (CVE-2026-60137), could allow an attacker to perform SQL Injection and achieve Remote Code Execution.”
  • CVE-2026-60137 — 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 to the parameter.”

Read carefully, the second CVE alone is not a universal disaster: something has to pass untrusted input into that parameter. The first one supplies exactly that, and does it without credentials. Hence the severity: the chain turns two mid-range defects into pre-authentication access. In MITRE ATT&CK terms this is a textbook T1190 — Exploit Public-Facing Application: “Adversaries may attempt to exploit a weakness in an Internet-facing host or system to initially access a network.”

One point of honesty, since that is probably the word that brought you here: “wp2shell” appears neither in the CVE records nor in the WordPress advisory. It is the label the industry attached to the chain. The official names are the two CVE IDs.

We stop here on the internals. The batch endpoint is no secret — it has been documented since 2020, was introduced in WordPress 5.6, accepts up to 25 sub-requests per call and lives at /wp-json/batch/v1 — but the mechanics of the attack are of no use to someone who has to defend, and the vulnerability is under active exploitation. What you need is to know whether you are exposed.

Am I vulnerable? The version matrix

This is the table that matters. It is derived from the NVD records and the official release announcement.

Your versionCVE-2026-60137 (SQLi)CVE-2026-63030 (RCE chain)Update to
earlier than 6.8not affectednot affectedunsupported anyway
6.8.0 to 6.8.5affectednot affected6.8.6
6.9.0 to 6.9.4affectedaffected6.9.5
7.0.0 to 7.0.1affectedaffected7.0.2
6.8.6 · 6.9.5 · 7.0.2 and laterfixedfixedyou are good

WordPress.org puts it plainly: “WordPress 6.9 is affected by both vulnerabilities”, “WordPress 6.8 is only affected by the first vulnerability”, “Versions of WordPress prior to 6.8 are not affected.” Watch that last line: not affected by these two CVEs does not mean safe. The standing rule still applies — “only the most recent version of WordPress is actively supported”.

Two notes on severity, with correct attribution, because the sources disagree and it is worth knowing. For CVE-2026-63030 the CNA (WPScan) assigns CVSS 9.8, CRITICAL, while the additional CISA-ADP record assigns 7.5, HIGH. For CVE-2026-60137 the relationship inverts: 5.9 (MEDIUM) from the CNA, 9.1 (CRITICAL) from CISA-ADP. There is no primary NVD score. The number that actually sets your priority, though, is none of these: it is that CISA added both CVEs to the Known Exploited Vulnerabilities catalog on 21 July 2026, with a remediation due date of 4 August 2026. What lands in the KEV catalog is what is known to be exploited in the wild.

How do I check the version from the command line?

On the server. With WP-CLI, one line:

# The installed version
wp core version

# With extended details (DB revision, package language)
wp core version --extra

Without WP-CLI, the version is in the dashboard under Updates, or in the number at the bottom right of the admin area.

And the “wp2shell checkers” that probe your site from outside? They are useful for getting a picture at scale, not for certifying your site. A remote check infers the version from readme.html or the generator meta tag: two things that a great many installs strip out as a hardening habit, that caches can serve stale, and that an attacker who is already in can edit. The upshot is that an external scanner can tell you “safe” when you are not — or raise an alarm over nothing. The authoritative check is the one done on the filesystem. If you run more than one site, this is exactly the difference between knowing and hoping: it is why Fenrir WP Bridge keeps the version inventory for every site in one place, instead of leaving you to open twenty dashboards.

Did automatic updates already save me?

Maybe. Do not assume it, and not because WordPress failed to do its part: for this release the project “enabled forced updates via the auto-update system for sites running affected versions”. Many sites updated themselves overnight on 17 July.

Four categories fall outside, and they are more common than they look:

  1. Sites under version control. Automatic core updates are disabled when WordPress detects a Git or SVN checkout.
  2. Sites with the AUTOMATIC_UPDATER_DISABLED constant set in wp-config.php, or with WP_AUTO_UPDATE_CORE set to false.
  3. Sites where WordPress cron does not run — because it was disabled, because traffic is thin, because it was replaced by a misconfigured system cron. An automatic update still needs something to trigger it.
  4. Sites installed before 5.6 and never reconfigured: up to that version the default only covered minor releases, and inherited configuration sticks.

In all four cases the site stayed on the vulnerable version while exploitation was already under way. Hence the rule: verify, do not infer.

How do I tell if they already got in?

If your site was exposed on a vulnerable version between 17 July and the moment you updated, updating is not enough: it closes the door, it does not evict whoever is already inside. Four checks, in order of yield.

1. Core file integrity. Compare every file against the official WordPress.org checksums:

wp core verify-checksums --include-root
wp plugin verify-checksums --all

--include-root is the flag that counts: without it you only see modified files; with it, you are also told about foreign files that appeared in the site root. A backdoor rarely modifies an existing file — it usually adds one. If you find something, what follows is the craft described in how to spot a web shell on WordPress: MITRE catalogues that persistence as T1505.003.

2. Administrators you did not create. This is the most immediate indicator of compromise after an RCE, and ATT&CK catalogues it as T1136.001 (Create Account: Local Account). The column that matters is the registration date:

wp user list --role=administrator \
  --fields=ID,user_login,user_email,user_registered

An administrator registered after 17 July that you do not recognise is an incident until proven otherwise. Ask the same question of editor-role users: a careful attacker does not always reach for maximum privilege.

3. Foreign scheduled tasks. WordPress cron is a convenient place to get yourself re-executed:

wp cron event list --fields=hook,next_run,recurrence

Look for hooks whose names belong neither to core nor to your plugins.

4. Web server logs. Look for POST requests to the batch endpoint, in the two forms it can take depending on permalinks:

grep -E 'POST .*(wp-json/batch/v1|rest_route=/batch/v1)' /var/log/nginx/access.log

Legitimate traffic to that endpoint exists — the block editor uses it — so it is not an alarm in itself. What matters is context: bursts from a single IP, anonymous user agents, requests from networks that have nothing to do with your editors, and above all a burst followed by suspicious appearances in the three checks above.

What do I do if I find something?

The official WordPress.org procedure for a compromised site is long; these are the points people get wrong most often.

  • Document before you clean. “The first actionable step you should take post-compromise is documentation”: it is the basis of the incident report, and hasty deletion destroys the evidence you need to work out how they got in.
  • Do not reinstall core from the dashboard. The official instruction is explicit: “When reinstalling, be sure not to use the reinstall options in your WP-ADMIN”, because those installers “often only overwrite existing files, and hacks often introduce new files”. You reinstall the same version over SFTP, replacing /wp-admin and /wp-includes.
  • Rotate the secret keys, not just the passwords. Changing passwords does not throw out anyone who already holds a session. The secret keys in wp-config.php have to be updated: “This will force anyone that might still be logged in off.”
  • Change credentials twice: once during cleanup and once after it, because “you need to change the passwords for your site after making sure your site is clean”.
  • Check .htaccess, in every directory where it appears: the official documentation flags it as the file most often modified for malicious purposes.

If the site handles customer or order data, the question stops being technical at this point and belongs with the people responsible for it. We stop where the craft ends: getting the site back up and understanding the vector.

Why monitoring matters more than any single patch

wp2shell demonstrates a structural problem, not an isolated case. The window between the fix being released (17 July) and the entry landing in the KEV catalog (21 July) is four days: that is how long it took to go from “a patch exists” to “it is confirmed that someone is exploiting this on real sites”. Inside that window, the difference between an updated site and a stalled one was not anybody’s skill: it was a cron job that either ran or did not.

Nobody reads the WordPress security announcement at two in the morning. But something has to notice: that a security release shipped, that three of your twenty sites did not take it, that one of those three has one more administrator than it had yesterday. That is the job of Fenrir for WordPress on the sites and Fenrir SOC on the servers: version inventory, file integrity, log correlation and a response that starts before you open a terminal. You apply the patch once. Checking that it is still needed is a nightly job.

Frequently asked questions

Which WordPress versions are vulnerable to wp2shell?

The full chain (unauthenticated RCE) affects WordPress 6.9.0 through 6.9.4 and 7.0.0 through 7.0.1. The SQL injection CVE-2026-60137 on its own also affects the 6.8 branch, from 6.8.0 to 6.8.5. The fixes are 6.8.6, 6.9.5 and 7.0.2, all released on 17 July 2026. According to WordPress.org, versions prior to 6.8 are not affected.

How do I find out which WordPress version I am running?

On the server, not from outside. With WP-CLI: `wp core version`. From the dashboard: Updates, or the version number at the bottom right of the admin area. Remote checks that read readme.html or the generator meta tag are only indicative: those markers are often removed or stale, so they can tell you 'safe' when you are not.

If automatic updates are enabled, am I already fine?

Probably, but verify it. For this release WordPress enabled forced updates for sites running affected versions. What falls outside: sites under version control, sites with AUTOMATIC_UPDATER_DISABLED or WP_AUTO_UPDATE_CORE set, and sites where WordPress cron does not run. Check the version — it is one command.

How do I tell whether my site has already been compromised?

Three checks, in this order: `wp core verify-checksums --include-root` for modified or foreign core files; `wp user list --role=administrator`, watching the user_registered column for administrators that appeared recently; `wp cron event list` for scheduled tasks you do not recognise. In the web server logs, look for POST requests to /wp-json/batch/v1.

I updated after 17 July — am I safe?

You are safe from new exploitation, not from exploitation that already happened. The update closes the door, it does not remove what came in before it: administrator accounts created, files uploaded, scheduled tasks. If the site sat exposed on a vulnerable version while exploitation was active, run the compromise checks after updating.

Sources