This is the engineering story of the last 48 hours: a critical WordPress core vulnerability, an exploitation wave that started within a day, and how we detected it, blocked it fleet-wide, hunted for damage, and shipped an open-source tool so anyone can check their own sites.
We are writing it up in detail because the decisions along the way say more about how we run WordPress hosting than any marketing page could. The short version: if your site runs on InstaWP, you did not have to do anything. Here is what happened underneath that.
The vulnerability
On 17 July 2026, WordPress shipped an emergency security release. Versions 7.0.2, 6.9.5 and 6.8.6 landed together to fix a flaw the security community nicknamed wp2shell, tracked as CVE-2026-63030.

It is the worst class of WordPress bug there is: a pre-authentication remote code execution in WordPress core. No login required, no unusual plugin required, reachable on a default install.
The flaw lives in the WordPress REST API, which every default install exposes. The exploit abuses how core handled a batch request and chains it with a SQL injection in a core database query.
Put together, that chain lets an unauthenticated attacker turn a single crafted HTTP request into code execution on the server. The same release also fixed a related SQL injection issue (CVE-2026-60137), which is why WordPress bundled both into one out-of-band update.
The exposure at a glance:
- Affected: WordPress 6.9.0 to 6.9.4, and 7.0.0 to 7.0.1 (plus the 7.1 beta). Installs older than 6.8 are not affected by the RCE.
- Fixed in: 7.0.2, 6.9.5 and 6.8.6.
- Why it is severe: pre-auth, works on a default install, and is trivial to script.
Because of that severity, WordPress also pushed the fix as a forced automatic security update, so many self-managed sites were patched without anyone lifting a finger. But auto-updates are switched off on a lot of sites, especially development, staging and agency-managed installs. Those are exactly the ones an automated wave finds.
The clock started immediately
A public proof of concept appeared on 18 July, the day after the patch. Automated exploitation began almost at once, the way it always does with a pre-auth core bug: the moment a working exploit is public, botnets start spraying it at every WordPress site they can find.
The dangerous window is not “someday”. It is the gap between disclosure and the point where every site is patched or protected, and that gap is measured in hours.
Most of our fleet was running affected versions, because InstaWP is a development and staging platform where people deliberately pin WordPress versions. We needed protection in place before the wave reached us, not after.
Why our edge could not catch it
The obvious question is why a CDN or edge firewall did not simply block this.
wp2shell arrives through the WordPress REST API, and REST traffic is a known blind spot for edge filtering. Many CDN and web application firewall setups do not deeply inspect REST API calls.
Plenty of platforms, ours included, deliberately let REST traffic pass the edge so legitimate API calls are never slowed down or falsely blocked. That is normally the right trade. Here it meant a generic edge rule would have waved the exploit straight through.
So the edge was the wrong layer. We had to neutralise the attack at the origin, in the web server sitting directly in front of every site’s application code.
The fix: an origin virtual patch
Within hours of the exploit going public, we shipped a virtual patch at the origin to the whole fleet.
A virtual patch is a protective rule that runs in the web server layer, in front of PHP. When a request matching the exploit’s shape arrives, the rule rejects it and returns a 403 before the request is ever handed to WordPress. PHP never runs. The database is never touched. The attempt stops at the front door.
Two engineering decisions shaped it.
Targeted, not blunt. We were not willing to ship protection that broke real work. The rule separates anonymous exploit traffic from legitimate authenticated activity, so the block editor, plugin operations and everyday logged-in usage on the same REST API keep working normally.
Verified, not assumed. We tested the block directly on each server: the exploit route returns 403, encoded variants return 403, authenticated batch calls still succeed, the homepage and general REST API stay at 200, and certificate renewals are untouched.
The rollout, and the gap we found in our own coverage
Shipping the rule was not the end of it. The honest part of this story is what we found when we went back to check.
Our protective rule only helps a site that actually includes it, and coverage was not uniform. Newer servers were in good shape. Some older ones, provisioned before the rule existed, were only partially covered. A block that protects most sites is not a block. It is a false sense of security.
So we wrote a reconciliation pass that safely added the rule to every site missing it: back up first, insert the rule, validate the config, reload, and roll back automatically on any failure. We ran it until every production server reported full coverage, with zero failures.
Finding that gap and closing it mattered more than the original deploy. It is exactly the kind of blind spot that turns “we shipped a fix” into “we thought we shipped a fix”.
We did not just block. We went hunting.
Blocking new exploitation is necessary but not sufficient. A pre-auth RCE with a public exploit means you have to assume attempts were already in flight before your block went live, and check.
So we ran a fleet-wide forensic sweep of our logs and sites. It confirmed that wp2shell was actively exploited against the fleet, and that a small number of sites were compromised in the window between disclosure and our block going live. Every confirmed case was created before that server’s protection was in place, which is the result you want: the block is holding against new exploitation.
The most useful lesson came from detection itself. This kind of attack leaves traces in more than one place: a signature in the request logs, and artifacts left behind on the site. No single check is complete. A scan that only looks at files on disk misses sites where the only evidence is in the database. You have to check every layer, fleet-wide, or you get a false “all clear”.
For the sites where we found evidence, we are remediating directly and monitoring closely.
One deliberate choice about this write-up: we are not publishing the exact request the exploit uses, or the specific indicators of compromise we hunt for. Those help attackers more than defenders. Instead, we put the checks into a tool.
We open-sourced the detection
Because this problem is not unique to us, we packaged our detection into a free, open-source scanner: wp2shell-scan.
It is read-only by default and checks the two places this attack leaves a trace: your server logs, for the request pattern the exploit uses, and your site’s files and users, for the artifacts a compromise leaves behind. Point it at one site or a whole batch and it tells you whether anything looks off.
It works whether or not your sites are on InstaWP, and because it only reads, it is safe to run on production before you decide what to do next.
Why we did not force-update your WordPress
A fair question: if the real fix is a core update, why not just push 7.0.2 to every site?
Because on a development and staging platform, customers pin their WordPress versions on purpose. Automatic core updates are off on most sites by design, because a forced version bump can break a client’s work in progress, a plugin under test, or a carefully reproduced bug. Which version a site runs is the owner’s call, not ours to make silently.
The origin virtual patch let us neutralise the live, automated threat without modifying a single customer file, while leaving the decision about when to update core with you. When you are ready, updating to the patched release is a one-click action from your dashboard.
What we changed for next time
The uncomfortable truth is that we were reacting to a public exploit rather than getting ahead of the advisory. So we have put proactive vulnerability monitoring in place: catch the next serious WordPress core, plugin or theme issue as it is disclosed, map it to a mitigation, and be ready to protect the fleet before an exploitation wave, not during one. This response worked. The next one should start earlier.
You did not have to do anything
That is the whole point.
If your site runs on InstaWP, there was no emergency for you. No 2am patch window, no scramble to work out which sites were on which version. We shipped protection fleet-wide while most of the internet was still reading the advisory, then went and checked our work.
Defence in depth doing its job: the platform absorbs the shock so the people building on top of it can keep building.
If you run WordPress somewhere else
The WordPress security team did the important work here, and the fix is available to everyone.
If you manage your own core, update to 7.0.2, 6.9.5 or 6.8.6 depending on your branch, today if you have not already. A virtual patch is a shield; the official release is the repair.
If you manage sites for clients, check every one of them, including the ones nobody has logged into for a year, because those are always the first to get hit. And if you want a fast way to check for signs of this attack, wp2shell-scan is free and read-only.
Vulnerabilities in WordPress core are rare, and pre-auth RCEs rarer still. But they will happen again, and the outcome is decided less by whether your host has a firewall and more by whether your host is watching, and whether they can move across their whole fleet in hours rather than days.
References
- WordPress security releases (WordPress News) — the emergency 7.0.2 / 6.9.5 / 6.8.6 announcement.
- CVE-2026-63030 (NVD) — wp2shell, the pre-auth RCE.
- CVE-2026-60137 (NVD) — the related SQL injection fixed in the same release.
- WordPress REST API Handbook — background on the API the exploit uses.
- Updating WordPress (documentation) — how to move to a patched version.
- wp2shell-scan (GitHub) — our free, read-only scanner for this vulnerability.