A real WordPress core RCE, and the two locks that would have stopped it
The wp2shell flaw let an anonymous request take over a default WordPress site. Patch first — then here is why two of Adminkeep's locks break the chain it relies on.
In July, WordPress core shipped a fix for a flaw that let a completely anonymous request take over a default install. No login, no vulnerable plugin, no unusual configuration — a stock site was enough. It was serious enough to earn a nickname, wp2shell, and it has been exploited in the wild since the middle of the month.
If you run WordPress, the first thing to do is update. The fix is in 7.0.2 and 6.9.5 (and 7.1). Everything below assumes you have already patched. Adminkeep is not a substitute for that, and this post will not pretend otherwise.
What is worth understanding is how the takeover finished — because the last two steps are the same last two steps in almost every WordPress compromise, and they are exactly what two of Adminkeep’s locks are built to refuse.
What happened
The flaw was a chain, not a single bug. Tracked as CVE-2026-63030 and CVE-2026-60137, it started with a confusion in how the REST API handles batched requests, reached a SQL injection through that gap, and used the result to make WordPress briefly act with an administrator’s identity.
In that window, the attack did two ordinary-looking things:
- It created a new administrator account through the normal
/wp/v2/usersendpoint. - It used that administrator to install a plugin — a plugin whose only job was to run the attacker’s PHP.
That is the whole game. A clever, unauthenticated front end, and then a mundane back end: make an admin, install something, run code. The rogue admin matters because it outlives the original hole — patch the bug, and the account is still sitting there.
Lock one: no new administrators
Adminkeep’s Registration Lockdown refuses to create an administrator account, and
it does so at the one place every route has to pass through. Whether the request comes
from the registration form, from the REST API, or from code already running with an
admin’s privileges, creating a user ends up calling WordPress’s wp_insert_user(). The
lock hooks the last filter inside that function and, if the new account would be an
administrator, aborts the write. Nothing is saved.
This is the layer that matters for wp2shell, and it is worth being precise about why. The exploit does not use the public “anyone can register” setting — closing the registration form would not have touched it. What stops it is the deeper guard that refuses the write itself, no matter how convincingly the request has arranged to look like an administrator. That guard is on by default, and it leaves ordinary customer registration — WooCommerce checkout, memberships — completely alone.
The rogue-admin step is step one of two. Refuse it, and the chain ends before code runs.
Lock two: nothing new gets installed
Installation Lockdown is the backstop for the other step. It denies the
install_plugins and upload_plugins capabilities to every user, so even a real
administrator — never mind a fabricated one — cannot add a plugin to the site. The final
move in wp2shell was to install code and run it; this closes that door directly.
It is opt-in rather than on by default, because freezing installs is a policy choice, not something to impose silently. But on a site whose plugins rarely change, it turns the most common “now run my code” step into a dead end. Activating what is already installed still works; updates keep arriving, so security releases are never held back; and you can switch the whole thing off from the settings screen whenever you need to.
What this is, and what it isn’t
Both of these are enforced in PHP. Anyone with filesystem, database, or WP-CLI access can step around them — they close the common automated paths that real attacks take, and that is the honest claim, not a guarantee. They are a second wall, not the first one.
The point of a second wall is that you never have to trust the first one completely. WordPress core is careful and well-audited, and it still shipped a pre-auth RCE this summer. Patching fixed that bug. Refusing new administrators and refusing new installs fixes the pattern — so the next bug, in core or in one of your plugins, has fewer places to finish.
Patch first. Then decide how much you want to lock down.
If you want the walkthroughs: stop unwanted user registration and block plugin installs and updates cover the two locks in detail.