XSS2Shell: an XSS on the WordPress login screen reaches code execution on the server
by Claudiu Hulea · IT Management Consultant
WordPress has patched a critical vulnerability in its own core, CVE-2026-64638, nicknamed “XSS2Shell”, that starts as an unauthenticated cross-site scripting flaw on the login screen and can be chained into code execution on the server. It is in the core, not a plugin, it affects essentially any installation left unpatched, and because WordPress powers around 43% of the web, the surface is enormous. If you run a WordPress site, update to 7.0.3 now.
What it is, briefly
It all starts on wp-login.php. When you submit a nonexistent username, WordPress echoes it back in an error message. Here, an unauthenticated attacker can slip in code that runs in the browser, a reflected XSS, without holding any account.
The jump from XSS to code execution on the server requires an administrator to open the page the attacker prepared. Through a chain that abuses that administrator’s session, the attacker ends up uploading a malicious plugin, and the plugin’s files run PHP code on the server. We are not spelling out the steps, but the idea is clear: from a login field to full control.
The cause: two cleaners that do not agree
The interesting part is the root cause, because it is a class of defect you see everywhere. WordPress runs the username through several sanitization layers. The first, wp_strip_all_tags, does not recognise a tag written with a space between the angle bracket and the name, for example < area, so it lets it through untouched. The second layer, wp_kses_post, correctly parses it as a valid <area> and allows it.
The two do not see the same thing. An input the first filter deems harmless becomes, at the second, a working HTML tag. That parser disagreement is exactly what opens the XSS. It is the same story as at any boundary where a check passes but the real effect differs from what the check assumed.
Why it is serious
Three reasons.
It is in the core of WordPress, not an obscure plugin you could uninstall. If you run WordPress unpatched, you are exposed.
It is pre-auth at delivery. The attacker does not need an account to send the payload, only an administrator who opens the link.
It already has a public exploit. According to reports, a tool that walks the whole chain appeared on GitHub within a day of disclosure. The reported CVSS score is high, around 8.9. At disclosure there was no confirmed evidence of in-the-wild exploitation, but with public code the window is already open.
Timeline
According to the researchers who found it, pwn.ai:
- 26 July 2026, discovery.
- 6 August 2026, WordPress ships the fix in version 7.0.3, backported to every maintained branch, back to 4.7.
- 7 August 2026, public disclosure.
One detail worth noting: the vulnerability was found autonomously by an AI system. It is a signal of the same direction we keep writing about, security research accelerated by machines, on both sides.
What to do
Defence has one mandatory step and a few that reduce exposure.
Update to 7.0.3, now. Sites with background auto-updates should already have it, but do not assume. Check the actual version of the installation, especially on self-hosted sites, where updating often needs manual intervention.
Review Application Passwords. The attack chain steals one of these application passwords. Revoke the unused ones and treat them as keys, not as a convenience.
Reduce the login screen’s exposure. Restrict access to wp-login.php and wp-admin with an IP allowlist, a WAF in front, or additional authentication. It does not stop this chain on its own, but it shrinks who can deliver the payload. The patch remains the real fix.
Monitor. A plugin installed unexpectedly, or new files under wp-content/plugins, are exactly the signal to watch for after this kind of attack.
The lesson
Beyond this CVE, the lesson is reusable. An input one filter declares clean can be seen differently by the next parser. Do not rely on having called a sanitization function, verify what actually reaches the HTML, in the context where it lands.
The correct defence is escaping at output, in the right context: HTML, attribute or URL. That is exactly what WordPress did in the fix, adding esc_html, esc_url and esc_attr at the point of display. Input sanitization helps, but correct output encoding is what closes the hole. It is the same discipline as “verify the effect, not the configuration”, moved into the web layer.
Want to know what versions and what plugins actually run on your sites, and who can reach the login screen? Get in touch and we start from a review.
Sources
Frequently asked questions
What is XSS2Shell (CVE-2026-64638)?
A WordPress core vulnerability that starts as an unauthenticated cross-site scripting flaw on the login screen (wp-login.php) and can be chained into PHP code execution on the server. It affects essentially any installation not updated to version 7.0.3. Because WordPress powers around 43% of the web, the surface is enormous.
What is the root cause?
A parser disagreement between two sanitization layers. The first, wp_strip_all_tags, does not recognise a tag written with a space between the angle bracket and the name (for example "< area"), so it lets it through. The second layer, wp_kses_post, correctly parses it as a valid "<area>" and allows it. The two do not see the same thing, and that disagreement opens the XSS.
Does the attacker need an account?
Not to deliver the XSS, which is unauthenticated. The jump from XSS to code execution on the server does require an administrator to open the page the attacker prepared. The chain abuses that administrator's session, ends up uploading a malicious plugin, and the plugin files run PHP code.
What should I do?
Update to WordPress 7.0.3 now; the fix is backported to every maintained branch, back to 4.7. Check the actual version of the installation, especially on self-hosted sites. Review and revoke unused Application Passwords (the chain steals one), restrict access to wp-login.php and wp-admin, and monitor for unexpected plugin installs.