wp2shell · July 2026
Pre-authentication remote code execution in Core, versions 6.8.0 through 7.0.1. No account, no click, no plugin required. Actively exploited since disclosure; webshells and rogue administrators are the typical leftovers.
Threat advisory · September 2026
Three names have been circulating in the same week, and they are being run together as “the new WordPress malware”. They are not one thing. Two are newly patched Core flaws with no confirmed abuse yet. The third is a July vulnerability chain that attackers have been using for two months to plant webshells and rogue administrators, and that is the one most of the compromised sites we are seeing this month trace back to. This advisory separates them, explains how each one works in plain English, and gives you the checks to run on your own sites today.
Published Last reviewed
Start here · plain English
If you run WordPress sites and only read one section, read this one. On 17 September 2026 WordPress shipped 7.1.1 with eleven security fixes. Two of them have been given catchy names: Click2Shell, found by Paulos Yibelo at pwn.ai, and Comment2Shell, found by Rafie Muhammad. Both are serious. Neither has been seen in a real attack at the time of writing, and both need a site administrator to do something — click a link, or simply look at a page — while logged in.
The name you should actually be worried about is the older one. wp2shell (CVE-2026-63030 and CVE-2026-60137) was published on 17 July 2026 and is a fully unauthenticated route to code execution on a stock WordPress install. Exploitation started within hours, CISA added it to the Known Exploited Vulnerabilities list four days later, and it is still being sprayed across the internet. When a site comes to us this month with a webshell and an administrator nobody created, the timeline almost always leads back to a July install that was not updated in time.
The practical consequence: the new flaws are a reason to update today. The old flaw is a reason to check whether you were already hit.
Pre-authentication remote code execution in Core, versions 6.8.0 through 7.0.1. No account, no click, no plugin required. Actively exploited since disclosure; webshells and rogue administrators are the typical leftovers.
A crafted link, opened by a logged-in administrator, silently installs a theme from WordPress.org and can chain into PHP execution through insecure code in that theme. Fixed in 7.1.1. Public proof of concept since 21 September; no confirmed attacks yet.
An anonymous comment carrying a line break inside an HTML attribute becomes stored script when WordPress reformats it. If an administrator views the page, the script can install a plugin as them. Fixed in 7.1.1. Not observed in the wild.
All three end in the same place — attacker-controlled PHP running on your server — and all three are closed by keeping Core current. The difference is how much the attacker has to do, and whether anyone has actually done it yet.
Click2Shell
Click2Shell is a good name because it describes the whole attack. The attacker does not need a WordPress account, a nonce, or a password. They need an administrator, already logged in, to open one URL. Phishing delivers that; so does any existing cross-site scripting bug on the site. Everything after the click happens in the administrator’s browser and on the server, without any further interaction.
The bug itself is small. The theme installer page in wp-admin takes a theme slug from the URL and drops it, unescaped, into a jQuery selector so that it can highlight the matching theme card. A slug ending in a few carefully chosen characters turns that selector into one that matches the card’s Install button instead — and the page then clicks it on the administrator’s behalf. The WordPress.org API, which interprets the same value more forgivingly, still returns a real theme from the catalog. The result is a silent installation of an attacker-chosen theme, with the administrator’s session supplying every permission and token the request needs.
That alone is a nuisance, not a compromise. It becomes one because WordPress loads a theme’s PHP when building a Customizer preview even if that theme is not active. A second crafted link opens the Customizer with the freshly installed theme, its functions.php runs, and whatever that theme registers is now live. The pwn.ai researchers found more than forty themes on WordPress.org whose pre-activation code was unsafe, and demonstrated the chain with Mobile Repair Zone 2.5.4, whose AJAX handler accepted a plugin download URL with no nonce and no capability check at all. WordPress fetched the attacker’s ZIP, unpacked it as a plugin, and executed it.
An administrator, logged into wp-admin, opens a link. The link points at theme-install.php on their own site with a theme parameter that ends in selector-breaking characters, for example twentytwenty"]>*>*>*/* once URL-decoded.
The installer page builds a selector from that slug without escaping it. The malformed selector matches the Install button of the theme card, the page fires a click, and WordPress installs an attacker-chosen theme from the official catalog. Nothing is shown to the administrator beyond a theme they did not ask for.
A follow-up link opens the Customizer with customize_theme set to the new theme’s slug. WordPress loads that theme’s PHP to render the preview even though a different theme is active on the site, so the theme’s functions.php executes.
In the demonstrated case the theme registers an admin-ajax action that installs and activates a plugin from any URL it is given, with no nonce and no capability check. The request that reaches it needs nothing from the attacker beyond the administrator’s existing session.
WordPress downloads the attacker’s ZIP, unpacks it into wp-content/plugins, and runs it. From this point the attacker has arbitrary PHP: new administrators, reading wp-config.php, modifying files, and everything else that follows from code execution as the web server user.
| Detail | What is known | Source |
|---|---|---|
| Core flaw | Unescaped theme slug in a jQuery selector on the theme installer page; fixed by scoping the selector to real theme cards and passing the slug through $.escapeSelector(). | pwn.ai; Patchstack |
| Severity | CVSS 7.1 for the Core flaw on its own; 9.6 for the full chain to code execution. No CVE identifier assigned at the time of writing. | The Hacker News; BleepingComputer |
| Affected | All WordPress versions before 7.1.1. Security backports were issued for supported older branches back to 4.7. | WordPress.org; pwn.ai |
| Second stage | Mobile Repair Zone 2.5.4 demonstrated; more than 40 catalog themes reported to carry comparable pre-activation code. Names beyond the example were not published. | pwn.ai |
| Preconditions | A logged-in administrator opens the link; file modifications are permitted on the site. Authors and Editors cannot install themes and cannot trigger the chain. | Patchstack; BleepingComputer |
| Timeline | Reported 22 August; patched 17 September; disclosed 18 September; public proof of concept 21 September 2026. WordPress paid its maximum bounty of $300. | pwn.ai; BleepingComputer |
| Exploitation | No confirmed in-the-wild use as of 22 September 2026. | All sources consulted |
WordPress 7.1.1
Click2Shell has taken the headlines, but 7.1.1 fixes eleven security issues. One of the others has its own name and deserves its own paragraph. Comment2Shell (CVE-2026-93485, rated 7.1 by Patchstack) is a stored cross-site scripting bug in wpautop(), the function that turns line breaks into paragraphs when a comment is displayed. A comment that passes WordPress’s sanitisation on the way in can be broken apart on the way out: a line break placed inside the attribute of an allowed HTML tag ends up moving attacker text into a position where it runs as an event handler. Nobody has to click anything. If a logged-in administrator so much as views the page, the script runs with their session and can upload a plugin, which is to say a webshell.
Two things limit it. The comment has to be rendered, so a site with moderation on and a moderator who reads before approving is protected by that habit — but comment moderation is a default that many sites relax, and the researcher notes it can be bypassed in practice. And the affected rendering path applies to block themes from Twenty Twenty-Two onward, so classic-theme sites are less exposed. It has not been seen in the wild.
The remaining fixes matter less individually but are worth knowing about, because several of them are the kind of authenticated flaw that turns a Contributor or Author account — cheap to obtain on any site with open registration — into something worse.
| Fix | Who can trigger it | Reported by |
|---|---|---|
| Stored XSS in wpautop() — Comment2Shell | Unauthenticated visitor, subject to comment approval | Rafie Muhammad |
| Crafted URL installs and previews an inactive theme — Click2Shell | Unauthenticated attacker via a logged-in administrator | Paulos Yibelo, pwn.ai |
| HTML API set_modifiable_text() comment breakout | Depends on calling code | Jeremy Felt, WordPress Security Team |
| Stored XSS in custom header themes | Authenticated | Jeremy Felt, WordPress Security Team |
| Site Administrator can network-activate a network-only plugin | Site Administrator on multisite | Jesse McNeil |
| Authenticated path traversal in the REST Templates controller | Authenticated | Anthropic |
| XML-RPC customize_changeset bypasses edit_css checks | Authenticated | Ben Bidner, WordPress Security Team |
| Contributor+ arbitrary post overwrite | Contributor | Anthropic |
| Private parent-post title leaked via attachment metadata | Authenticated | HDWSec |
| Draft and pending post slug disclosure | Contributor | Jakub Herman |
| Comments and notes can be reparented by any authenticated user | Any authenticated user | Justin Hart, Viridis Security |
wp2shell · the campaign that is actually running
wp2shell is the reason this advisory exists. It is a chain of two Core bugs, disclosed by Searchlight Cyber on 17 July 2026 and fixed the same day in WordPress 7.0.2, 6.9.5, and 6.8.6. CVE-2026-63030 is a route-confusion flaw in the REST API batch endpoint that lets an anonymous request reach routes that should require authentication. CVE-2026-60137 is a SQL injection in the author__not_in argument of WP_Query, reachable through the posts endpoint’s author_exclude parameter. Chained, they give an attacker who has never logged in full read and write access to the database — and from there a new administrator, a plugin upload, and arbitrary PHP. Every default install running 6.9.0 through 7.0.1 was vulnerable to the full chain; 6.8.x was vulnerable to the injection alone.
Exploitation began the evening of the disclosure. Patchstack was reporting attacks by 7 PM Eastern on 17 July, VulnCheck had counted more than two dozen distinct public exploits by 19 July, and CISA added the flaw to its Known Exploited Vulnerabilities catalog on 21 July. CrowdSec’s network then watched 62,802 distinct IP addresses send matching requests between 20 July and 22 August, peaking at over 158,000 signals in a single day, with the number of distinct daily sources still climbing when the observation window closed. Wiz measured that 60 percent of organisations using WordPress had at least one vulnerable instance on the day of disclosure and a quarter had one exposed to the internet.
This is not only mass scanning. GreyNoise tracked a single actor through at least 49 compromised organisations in 29 countries — mostly small businesses and government bodies — including a Western government agency from which more than 18,500 records containing plaintext passwords and personal data were pulled out of the backend database on 22 July. The post-compromise pattern was consistent: install a webshell, dump the administrator table, create a disguised user, read wp-config.php and any other credentials on disk, then use those to reach the database directly and try the same passwords elsewhere on the host.
A minimal PHP file that evaluates whatever arrives in a POST parameter and otherwise returns a 404, so a scanner or a curious administrator requesting it sees a missing page. Observed by Wiz; multiple SHA-1 hashes published.
A 150 KB plugin disguised as “CMSmap”, with a file manager, database client, port scanner, batch code injector, and several privilege-escalation modules, packed with hex-concatenated strings and gzip-compressed base64 unpacked at runtime. Observed by Wiz and reported widely.
A plugin that registers its own REST endpoint under a /morning/v1/ namespace with a permission callback that allows everyone, and executes base64-encoded commands sent in a POST parameter. Observed by Wiz.
More than 100 backdoor administrator accounts counted in one honeypot set. Community scanners look for usernames of the form wpsvc_, wp2_, or w2s_ followed by hex, and for administrator emails at domains such as wp2shell.*, wordpress-svc.internal, and wordpress-noreply.net.
Webshells dropped as wp-content/plugins/<plausible-name>-<six hex characters>/<same>.php, taking a command in a c parameter. This is the pattern the InstaWP and Pantheon cleanup scripts key on.
Attempted installation of the Golang-based Overlord remote access trojan after initial access, per The Hacker News. Credential harvesting, local file inclusion against wp-config.php, and user enumeration through the REST users endpoint were all observed alongside it.
| Date | Event | Source |
|---|---|---|
| 17 July 2026 | wp2shell published; WordPress 7.0.2, 6.9.5, and 6.8.6 released. First exploitation reported the same evening. | Searchlight Cyber; Patchstack; VulnCheck |
| 19–20 July | More than two dozen public exploits; VulnCheck and Wiz observe in-the-wild exploitation and mass scanning. | VulnCheck; Wiz |
| 21 July | CISA adds CVE-2026-63030 to the Known Exploited Vulnerabilities catalog. | CISA via multiple reports |
| 22 July | GreyNoise-tracked actor compromises a government agency site and exfiltrates 18,566 records. | GreyNoise via CyberInsider |
| 26 July | Peak observed volume: 158,259 exploitation signals in one day. | CrowdSec |
| August | Source population keeps growing to over 10,000 distinct IPs per day while daily volume stays flat — automation, not a single operator. | CrowdSec |
| September | Sites patched late in July still surfacing with webshells and rogue administrators. New Core release 7.1.1 closes Click2Shell and Comment2Shell. | Our own casework; WordPress.org |
Check your own site
Run these from a trusted device. Each one reads and records; none changes anything. If any check produces a result you cannot explain, stop, preserve what you found, and move to the response section rather than deleting it.
wp core version, or the Updates screen. Anything below 7.1.1 (or below the matching security release for an older supported branch) needs updating now. Write down which sites were on 6.8.0–7.0.1 between 17 July and their update date; those are the sites the rest of these checks are about.
wp theme list, or Appearance → Themes. An inactive theme nobody on your team installed is the fingerprint of a Click2Shell forced install. Record its slug and the directory’s creation time before removing it. Note that a forced install alone does not prove the chain completed; the plugin check below does.
wp plugin list, then ls -la wp-content/plugins. Look for a plugin directory named with a plausible word and a six-character hex suffix, for “CMSmap” or any security plugin you did not install, and for any plugin whose directory holds a single small PHP file. Compare timestamps with your July update date.
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered. Look for logins of the form wpsvc_, wp2_, or w2s_ plus hex, for emails at domains you do not recognise, and for any account registered on or after 17 July that nobody can vouch for.
For wp2shell: POST requests to /wp-json/batch/v1 or ?rest_route=/batch/v1, especially any that returned 200 or 207 — Wiz reports a 207 Multi-Status on that endpoint as a high-fidelity sign of success — and any user agent containing wp2shell or rezwp2shell. For Click2Shell: requests to theme-install.php with a theme parameter containing quotes or brackets, followed by admin-ajax.php with wp_customize=on and a customize_theme you did not choose.
wp core verify-checksums for Core, then a scan of wp-content/uploads, wp-content/cache, and mu-plugins for PHP files. A one-line file that evaluates a POST parameter and otherwise returns a 404 is the wp2shell first-stage shell and will not look like much.
wp cron event list for scheduled tasks you do not recognise, and a request to /wp-json/ to list registered REST namespaces — an unfamiliar namespace such as morning/v1 is a backdoor route. Also review Application Passwords under each administrator’s profile.
For Comment2Shell, look in pending and approved comments for HTML tags whose attributes span a line break. There is no observed exploitation to match against yet, so treat this as a low-cost look rather than a primary indicator.
| Signal | Which flaw it points to | What raises concern | First safe action |
|---|---|---|---|
| Core below 7.1.1 | All three | Any site still on an unpatched version, especially one that spent time on 6.8.0–7.0.1 in July. | Update now; then continue the checks for that site rather than stopping. |
| Unfamiliar inactive theme | Click2Shell | A theme from the WordPress.org catalog that nobody installed, created after 18 September. | Record slug and timestamps, check the plugin list and logs for the follow-on chain, then remove. |
| Unfamiliar plugin or plugin directory | wp2shell, Click2Shell, Comment2Shell | A hex-suffixed directory, a single-file plugin, “CMSmap”, or any security tool you did not add. | Preserve a copy and its hash; do not activate or open it in a browser; treat the site as compromised. |
| Unknown administrator | wp2shell first; any of the three | Registration after 17 July, a generated-looking login, or an email at an unfamiliar domain. | Export the user row and metadata, then revoke sessions and remove after credential rotation begins. |
| Batch endpoint traffic with 200/207 responses | wp2shell | POSTs to batch/v1 that succeeded, or user agents naming the exploit. | Correlate with the timeline of files and users; assume the injection ran if responses succeeded. |
| Theme-install and customize_theme requests you did not make | Click2Shell | Selector characters in the theme parameter, followed by a Customizer load of that slug. | Identify which administrator’s session was used and assume their browser or inbox was the lure’s delivery path. |
| Unknown REST namespace or cron event | wp2shell | A namespace or hook that no installed plugin explains. | Locate the code that registers it; it is the persistence you would otherwise miss. |
Response
Everything in this section applies to a site where you found evidence of compromise, whichever flaw let it in. The attacker’s first actions after any of these three chains are the same — a new administrator, a webshell, a copy of wp-config.php — and so the response is the same too. Our WordPress site keeps getting hacked guide explains why sites that skip the middle steps come back within weeks.
Copy the suspicious files with their hashes and timestamps, export the users and usermeta tables, and pull the web server access logs covering July onward before rotation or cleanup overwrites them. Log retention on shared hosting is short; this is the first thing to run out.
Update to 7.1.1. If any site must stay on an older version for a short period, block POST requests to /wp-json/batch/v1 and the rest_route equivalent at the web server or WAF, and enable DISALLOW_FILE_MODS in wp-config.php, which prevents the forced theme install and the plugin upload that both Click2Shell and Comment2Shell depend on. Neither is a substitute for the update.
Database password, WordPress salts, every administrator password and application password, SMTP, payment and API keys in wp-config.php or plugin settings, and the hosting-panel and SFTP credentials of the account. Rotate from a trusted device; the compromised site is not one.
Delete rogue administrators, revoke all sessions, remove unknown application passwords and SSH keys, and check the hosting panel for users or API tokens added since July. GreyNoise’s actor moved from the site to the database to the host; assume yours did too.
Replace Core, every plugin, and every theme from fresh downloads rather than editing suspicious lines out. Remove the forced-install theme, the disguised plugin, and any PHP in uploads, cache, or mu-plugins. Diff the active theme against its original to catch the injected call you were not looking for.
Review autoloaded options for encoded blobs and injected script, remove unknown cron events, and remove any REST route the rebuilt code no longer registers. The wp2shell first stage lived in the database before it ever touched a file.
If the site shares a hosting account, a server, or a database server with others, the credentials it held reach them. Run the checks above on every site in that boundary before declaring any one of them clean. On a control-panel server, that means a root-level review, not a per-site scan.
Re-run the checks after caches expire, cron has fired, and real traffic has returned. Then keep watching the administrator list and the plugin directory for the next month; the reinfection case study shows what happens when that step is skipped.
Agencies, hosts, and fleets
Every one of these flaws was fixed on the day it was disclosed. The sites that got hit are the ones where automatic updates were off, DISALLOW_FILE_MODS or a disabled WP-Cron silently prevented background updates, or nobody owned the update. Inventory Core versions across the fleet today and find out why any site is behind.
Click2Shell and Comment2Shell ride a logged-in administrator. An agency employee logged into thirty client sites at once is thirty targets from one phishing email. Shorter sessions, a separate browser profile for wp-admin, and no shared administrator accounts reduce the blast radius.
The wp2shell post-compromise pattern is to read wp-config.php and then reuse what it finds. A database user shared across sites, or a hosting password reused across accounts, means one exploited site hands over the rest.
A fleet where every site was patched by 18 July still needs the administrator and plugin checks on each one. Sampling a few and extrapolating is how the rogue administrator on site 27 stays until October.
A WAF rule on batch/v1, rate limiting on theme-install.php and admin-ajax.php, and geo or reputation filtering on wp-login.php do not replace updates, but they make the next Core flaw a slower problem than this one was.
Most plugin scanners will flag the CMSmap plugin and the one-line shell. Few will flag a legitimate catalog theme that was installed by force, or an administrator with a plausible name. The checks in this advisory are ones a person has to run.
Sources
This advisory was compiled on 22 September 2026 from the published sources below, together with our own casework from the past two months. Figures are quoted as the source reported them and were not independently re-measured. Where a claim rests on a single source, that source is named next to it in the text.
Common questions
No. It is a vulnerability in WordPress Core — a way in — and it has been fixed. What arrives through it would be malware: a theme with an unsafe handler, then a plugin that acts as a webshell. Reports calling it “the new WordPress malware” are conflating the door with what walks through it. As of 22 September 2026 nobody has published evidence of it being used in a real attack.
For Click2Shell and Comment2Shell, yes, provided nothing had already happened. For wp2shell, only if the site was also on 7.0.2, 6.9.5, or 6.8.6 within a day of 17 July. If it spent longer than that on a vulnerable version, run the administrator, plugin, and log checks in this advisory before you rely on it.
Not on that evidence. The observed first stage is a one-line PHP file that returns a 404 to anyone who visits it, and the observed persistence is an administrator account with a plausible name. Neither changes what the site looks like. Check the user list sorted by registration date, the plugin directory, and the access logs for successful batch/v1 requests. If the logs from July are already gone, that itself is a reason to run the file and user checks carefully.
Partly, and only against two of the three. Setting it prevents the forced theme installation in Click2Shell and the plugin upload that Comment2Shell relies on, so both chains stall before code execution. It does nothing against wp2shell, which needs no file modification to create an administrator or run SQL. It also silently stops automatic Core updates, which is how several sites ended up vulnerable in the first place. Use it deliberately, with a separate update process, or not at all.
They will generally flag the known wp2shell webshells and the CMSmap plugin once signatures exist. They are unlikely to flag a legitimate WordPress.org theme that was installed by force, an administrator with an ordinary-looking name, or a REST route registered by a plugin they consider benign. Treat a clean scan as one input, and run the checks in this advisory as the others.
Core versions first, across everything, and find out why any site is behind. Then the administrator list on every site that was on 6.8.0–7.0.1 after 17 July. Then plugins. If any site shares a database server, hosting account, or credentials with others, treat that group as one boundary and finish the checks on all of it before declaring any one site clean. We scope this as a fleet review with per-site retesting; the contact page is the quickest route.
Yes. If Click2Shell or Comment2Shell exploitation is confirmed, if CVE identifiers are assigned, or if the list of affected themes is published, the modified date at the top will change and the relevant section will say what changed.
Choose the response path
One site, one worrying result
Best for an owner who found an unexplained administrator, an unfamiliar plugin or theme, or successful batch-endpoint requests in the logs and wants it handled properly rather than deleted and hoped for.
Agency, host, or fleet
Best when many sites share hosting, credentials, or one team of administrators, and the question is which of them were hit rather than whether one was.