Key Points
Over the weekend a pre-authentication remote code execution vulnerability (wp2shell) was dropped for WordPress Core. WordPress is a hardened target that powers well over 500 million sites across the internet.
Intruder’s security engineering team worked over the weekend to deliver emerging threat scans for our customers to detect wp2shell on their systems without them needing to log in and run a scan. Quality vulnerability management (VM) is multi-faceted and complex, and the three detection checks we produced for wp2shell provide an excellent case study for learning more about the challenges of VM.
What is wp2shell?
wp2shell is a pre-authentication remote code execution (RCE) chain that combines two separate flaws, an authentication bypass (CVE-2026-63030) and a SQL injection (CVE-2026-60137). The first part, the authentication bypass is a route confusion bug in the REST API batch endpoint. When a crafted batch request with a malformed path hits serve_batch_request_v1(), the validation and execution loops fall out of sync, causing WordPress to validate one request but execute the next one's handler. This bypasses all permission checks on the endpoint.
The second part is a SQL injection in `WP_Query`'s `author__not_in` parameter. Normally this parameter gets sanitized before it reaches a query, but the route confusion means it never passes through that validation step.
When both vulnerabilities are chained together, an unauthenticated attacker can execute arbitrary SQL against the WordPress database. From there, the full chain escalates through cache poisoning, changeset manipulation, and hook abuse to create an administrator account and achieve code execution via plugin upload. For a full technical breakdown of the exploit chain, Searchlight Cyber's research covers the discovery and each stage in detail.
How vulnerability checks work
At a high level, when a scanner checks for a vulnerability, it generally uses one of two approaches: version checks and active checks.
Version Checks
Version checks do what they say on the tin, they attempt to identify the version of the target application and compare that to known vulnerable versions. If the identified version falls within the vulnerable range, an issue is raised. This type of check is fast and easy to produce, however they are often weak checks which cause false positives or false negatives because they do not directly confirm the presence of the vulnerability itself.
Version checks will fail when an application strips the version number or doesn’t expose it, which is common in production deployments. Additionally, as the application changes over time, the format may change, the location of the exposed version moves, or it may be removed from the application entirely. These issues cause false negatives.
False positives can occur for several reasons as well. For example, when the server employs backporting, the version remains the same but a security patch is deployed into the ‘vulnerable’ version. The version appears vulnerable, but the code itself is patched. There are other ways in which version checks cause false positives outside of backporting too, such as when a specific configuration must be used for the vulnerability to work: the version number does not reflect that this configuration is in place.
This doesn’t mean that version checks are inherently bad, and they do provide some value. They can work well for targets behind web application firewalls (WAFs) or other protection layers that block active exploitation attempts. If you can reliably read a version string, you can still flag the risk even when the affected code is not accessible.
Active Checks
Active checks work by directly interacting with the vulnerable host to invoke a behaviour that would only happen if it is vulnerable. If the active check is solid, it cannot fall foul of many of the false positive and false negative problems that version checks have. Though they are more reliable in most cases, they also take much more time and expertise to produce. This is because the full exploit chain needs to be identified, often with minimal information available to the researcher. Skills like reverse engineering, patch diffing, and knowing the right places to look to find public exploit information are essential.
Active checks typically work by causing either a specific response or an out of band request which could not have happened if the machine was not vulnerable. For example, if the vulnerability is a SQL injection then injecting a SLEEP command to cause the response to be delayed is a safe and reliable (when used carefully) way to be sure that the SQL executed and that the server is therefore vulnerable. Though using a SLEEP isn’t 100% reliable either (and out of band methods should be preferred where possible), active check types like these cause the server to directly behave in a certain way only when they are vulnerable, and therefore they are the preferred option over version checks at Intruder.
Active Check Safety
Once the exploit mechanism has been identified, a safe and reliable version of the exploit needs to be assembled in order to produce an active check that can be run as part of an automated vulnerability scan. If the vulnerability leaves an admin user hanging there with no password, or a webshell exposed to the internet, it would do more harm than good.
Writing an active check for wp2shell
The first active check we produced for wp2shell sends two requests to the target application.
The first request sends a crafted batch payload to the WordPress REST API. On a vulnerable WordPress instance, the route confusion causes a nested `207` response containing `parse_path_failed`. A patched instance handles the batch normally and never produces this response structure. This confirms the structural flaw in serve_batch_request_v1() is present and reachable. This indicates we are dealing with an unpatched instance of WordPress and we can move to the step of directly confirming the vulnerability.
The second request goes further to exploit the SQL injection part of the wp2shell chain. It sends a batch payload that exploits the route confusion to inject a SLEEP(7)call through the author_exclude parameter. If the response takes more than seven seconds to come back, there is a high chance the SQL injection has been executed. At this point we know that this vulnerability actually exists and is no longer assumed, the vulnerable code path is reachable and we are confident that the application can be exploited.
In the case of wp2shell, the full RCE chain is actually several steps longer than this stage. However, as it continues it starts to interact with the database, store rows, and then start executing processes as an administrator. As a VM provider, we have to strike a balance between solid detection which is high confidence, and not interfering with vulnerable hosts more than is necessary. After all, if a customer host gets compromised, they’ll want to review logs of attacker activity without having to filter out their scanner.
Why active checks for wp2shell are more effective
Within the WordPress ecosystem there are a large number of security related plugins, and there are several which explicitly strip the version number so it’s harder to enumerate the version without logging in. This makes it unreliable to identify vulnerable WordPress servers instances based on their version numbers.
During the weekend, an early piece of remedial advice was to introduce a custom plugin that disables unauthenticated access to the vulnerable API, thus closing the loop on CVE-2026-60137, one part of the chain.
Both of these problems would make it extremely difficult for any version check to reliably detect this vulnerability. It would tell us the WordPress version falls within the affected range, but not whether the specific code path is reachable, whether some configuration or plugin has inadvertently mitigated the issue, or whether a reverse proxy is silently blocking the batch endpoint entirely. And for something as impactful as this vulnerability, speed and accuracy are incredibly important.
When middleware gets in the way
This is when things get more difficult for the active check. Middleware such as reverse proxies, defensive layers like WAFs, or even caching can all affect the scanner's ability to assess the target with an active check. Each of these can make a vulnerable target look patched from the outside, which causes dangerous false negatives.
For example, Cloudflare were quick to react and deployed a WAF rule to all customers over the weekend. This means that since that rule was implemented, a large number of WordPress instances could have been running vulnerable code and still not respond the way a scanner expects due to Cloudflare intervening between the scanner and application. Thus making the application appear as if it is not vulnerable.
This is one of the biggest challenges with vulnerability detection at scale (I regret all the bad things I said about vulnerability scanners when I was a pentester…). The further the application sits behind middlewares or protective layers, the harder it becomes to determine the actual state of the application.
So with this in mind, we hunted for a WAF bypass for our second active check.
WAFs and the bypass problem
WAF providers operate under constraints that make perfect detection impractical. They protect millions of sites simultaneously and need rules that are fast to evaluate, low on false positives, and deployable as quickly as possible after a vulnerability is disclosed. This means pattern matching on known proof of concept payloads, not deep analysis of every request, nor building large lists of potential bypasses for each vulnerability.
With the Cloudflare rule mentioned above, we found that this was effective at blocking the initial public proof of concepts, and blocking our own initial active check payload. However, we found that with a small modification, the request passed through to the application and the vulnerability was fully exploitable again, even with Cloudflare in front. Cloudflare didn’t have time to sit and understand the nuance of the application, the vulnerability, and the way PHP works (register_globals strikes again!).
This isn’t a critique of Cloudflare themselves, this is just an example of the cat and mouse game that WAFs have to play in order to act fast when reacting to new vulnerabilities. The attacker only needs to find one encoding issue, one parameter format, or one legacy PHP behaviour that the rule didn't account for. The WAF vendor has to anticipate all of them in a very tight timeframe. And of course, our WAF bypass won’t last forever either, because if Cloudflare catches wind of it (they will) - they will add a rule. But at this critical time, even our customers that haven’t allowlisted us through the WAF will have their vulnerable servers flagged.
The same advice from us still applies to those who use a WAF as a primary line of defense: WAF’s buy you time, but they do not fix the underlying vulnerability. The only way to fix it is by patching.
The version check backstop
And of course, the third check we wrote for wp2shell is a version check. We have fully automated flows to build version checks for us, which act as a good backstop for when active checks fail. For example, if Cloudflare adds a new rule to block our bypass, then some customers may again be in the sticky situation of their vulnerable server not being properly flagged, and version checks can in some cases still catch those where active checks fail.
What this means for your VM program
wp2shell is a good example of why vulnerability management is rarely a single yes or no check. As this post shows, no one method was enough on its own, which is why we shipped three checks rather than one.
This is the kind of judgement call behind our emerging threat scans. When something like wp2shell drops, we build the checks to make sure detection can happen effectively, automatically, with no intervention needed on your end. Sign up to get our emerging threat checks.




