# WordPress Core XSS2Shell Vulnerability Chains Pre-Auth XSS to RCE (CVE-2026-64638)

> pwn.ai disclosed XSS2Shell (CVE-2026-64638, CVSS 8.9), a WordPress core flaw exploiting a parser disagreement between PHP's strip_tags() and WordPress's KSES sanitizer to smuggle live HTML into the unauthenticated login page. Via DOM clobbering and REST API JSONP/Same Origin Method Execution abuse the reflected XSS can escalate to full remote code execution if a logged-in administrator is lured into clicking an attacker-controlled page. WordPress 4.7 through 7.0.2 are affected; WordPress 7.0.3 (released 2026-08-06) patches the issue.

- **Published:** 2026-08-07T00:00:00Z
- **Last reviewed:** 2026-08-09T04:50:11.333Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-1933
- **ID:** TL-2026-1933
- **Severity:** HIGH (CVSS 8.9)
- **Category:** VULNERABILITY
- **Status:** ACTIVE
- **Detections:** 9 · **IOCs:** 30 (full data via the Threadlinqs MCP server — Purple tier)
- **CVEs:** CVE-2026-64638

## Description

XSS2Shell (CVE-2026-64638) is a pre-authentication cross-site scripting vulnerability in WordPress core's login page (wp-login.php) that can be chained into remote code execution. The root cause is a parser disagreement in the username-processing pipeline: a failed login attempt passes the submitted username through wp_authenticate_username_password(), then sanitize_user()/wp_strip_all_tags() (which rely on PHP's strip_tags()), and separately through wp_kses_post(). PHP's strip_tags() only recognizes an HTML tag when '<' is immediately followed by a letter — pwn.ai demonstrated that strip_tags('<area id=test>') returns '' (stripped) while strip_tags('< area id=test>'), with a single space after '<', returns the string unchanged (survives). WordPress's KSES sanitizer, however, re-parses that same malformed string and treats the whitespace-separated '< area' as a legitimate <area> element, allowlisting it with attributes such as id, class, and href. A malformed username therefore reaches the failed-login error page as live, attacker-controlled HTML with no authentication required.

pwn.ai's proof-of-concept injects three chained elements: '< area id=ajaxurl href=/?rest_route=/&_method=GET&_jsonp=alert>', '< div id=color-picker class=reset-pass-submit>', and '< button class="wp-generate-pw color-option">X'. These weaponize DOM clobbering: an element with id="ajaxurl" becomes accessible as the global window.ajaxurl per the HTML living-standard named-property-resolution rule (section 7.3.3), which wp-includes/js/user-profile.js reads when it issues jQuery AJAX/REST calls on password-reset-related UI. The #color-picker and .reset-pass-submit-classed elements satisfy user-profile.js's DOM-selector guard checks that are absent on the bare login page, so undefined-value comparisons pass checks that should have blocked execution. jQuery coerces the clobbered ajaxurl through .toString(), which returns the injected <area>'s href attribute, redirecting the resulting $.post() call to an attacker-chosen same-origin REST endpoint carrying _method=GET and _jsonp=alert. WordPress's REST API supports an undocumented/hidden JSONP mode (reachable at endpoints such as /wp-json/wp/v2/users/1?_jsonp=ATTACKER_INPUT) that wraps any REST JSON response as a caller-named JavaScript function invocation; when hosts block anonymous REST fully, the companion _envelope=1 parameter wraps an HTTP 401 denial inside an HTTP 200 body so jQuery's status check still processes it as executable script.

WordPress sanitizes the _jsonp callback name with preg_replace('/[^\\w\\.]/', '', $callback) — an allowlist of only word characters and dots. This still permits dotted property-access chains, enabling Same Origin Method Execution (SOME), a CSP-bypass primitive originally published in 2022 by researcher Paulos Yibelo and reused here by pwn.ai in a companion write-up ('Bypass CSP using WordPress by abusing Same Origin Method Execution'). By setting the JSONP callback to window.opener.approve.click (a specific instance of the general window.opener.<property-chain>.click pattern, e.g. window.opener.wpbody.firstElementChild.firstElementChild.nextElementSibling....click), the payload reaches across a window.opener boundary and programmatically invokes a button's .click() method in the opener window without any user interaction there — even though the response content itself never executes as attacker-arbitrary JavaScript, only as a chain of legitimate DOM property/method references built from characters the regex allows.

Weaponizing this into RCE requires a second stage: the attacker must lure a logged-in Administrator to open a malicious third-party page (one click, per pwn.ai's PoC). That page opens a child window, navigates the opener to WordPress's /wp-admin/authorize-application.php Application Password approval screen, and fires the SOME payload from the child to auto-click the 'Approve' button in the opener. WordPress's auth-app.js script then creates a new Application Password and redirects the browser to the attacker-controlled success_url with the credential embedded in the query string (observed pattern: ?site_url=https://target&user_login=admin&password=XXXX+XXXX...). With a valid Application Password, the attacker authenticates to the REST API over HTTP Basic auth, publishes admin-authored page/post content using the unfiltered_html capability to embed same-origin <script> content, has that script fetch the plugin-upload form to extract a valid nonce, and submits a plugin ZIP archive to /wp-admin/update.php?action=upload-plugin. WordPress validates the nonce and the administrator capability (both correct, since the request legitimately carries the stolen Application Password's authority) and extracts the ZIP into wp-content/plugins/ without requiring plugin activation; PHP files inside the extracted directory (e.g. /wp-content/plugins/payload/shell.php) execute on direct URL access, granting the attacker full PHP code execution on the server — exposing database credentials in wp-config.php, enabling persistent administrator account creation, content manipulation, and OS-level command execution with the web server's PHP-worker privileges.

The flaw affects all actively maintained WordPress branches from 4.7 through 7.0.2 — pwn.ai and multiple outlets describe an installed base of roughly 500 million self-hosted websites, cited as approximately 43% of internet-facing sites running WordPress in some form. WordPress was notified 2026-07-27 and shipped WordPress 7.0.3 on 2026-08-06 (release led by John Blackbourn, with 60+ contributor acknowledgments; a WordPress 7.1 RC2 build with the same fixes was also published), bundled with fixes for 11 other, lower-severity issues disclosed in the same release: four Contributor+ stored-XSS bugs (emoji settings, Post Content block, Quick Edit with many users, Post Date block), a multisite user-registration privilege-escalation bypass, an information-disclosure bug in the Latest Comments block exposing password-protected post comments, post-slug enumeration, a comment-feed note-disclosure issue, an Author+ CSS-injection bypass of the safe-CSS filter (credited to Anthropic), an email-confirmation-flow bypass, and an SSRF in URL validation permitting requests to link-local address ranges. As of the coordinated disclosure on 2026-08-07 there is no public proof-of-concept exploit code beyond pwn.ai's own controlled demonstration (run against a clean local WordPress 7.0.2 install) and no confirmed in-the-wild exploitation; the CVE does not appear in the CISA Known Exploited Vulnerabilities catalog. pwn.ai explicitly cautioned that common WordPress hardening measures should not be treated as complete mitigation for the underlying XSS, and that applying the security update is required — the chain works against default installations with no unusual hosting prerequisites.

## MITRE ATT&CK

- T1190 Exploit Public-Facing Application
- T1059.007 Command and Scripting Interpreter: JavaScript
- T1204.001 User Execution: Malicious Link
- T1528 Steal Application Access Token
- T1552.001 Unsecured Credentials: Credentials In Files
- T1098 Account Manipulation
- T1136 Create Account
- T1505.003 Server Software Component: Web Shell
- T1005 Data from Local System
- T1071.001 Application Layer Protocol: Web Protocols
- T1565.001 Data Manipulation: Stored Data Manipulation
- T1203 Exploitation for Client Execution
- T1068 Exploitation for Privilege Escalation
- T1211 Exploitation for Stealth
- T1550.001 Use Alternate Authentication Material: Application Access Token
- T1185 Browser Session Hijacking
- T1105 Ingress Tool Transfer
- T1566.002 Phishing: Spearphishing Link
- T1027 Obfuscated Files or Information

## Sources

- [WordPress XSS2Shell Vulnerability](https://cybersecuritynews.com/wordpress-xss2shell-vulnerability/)
- [XSS2Shell: WordPress Preauth XSS to RCE Chain (CVE-2026-64638)](https://pwn.ai/blog/xss2shell)
- [Bypass CSP using WordPress by abusing Same Origin Method Execution](https://pwn.ai/blog/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution)
- [WordPress 7.0.3 Security Release](https://wordpress.org/news/2026/08/wordpress-7-0-3-release/)
- [New WordPress Pre-Auth XSS Could Lead to PHP Code Execution - Patch ASAP](https://thehackernews.com/2026/08/new-wordpress-pre-auth-xss-could-lead.html)
- [WordPress 7.0.3 Released: 12 Vulnerabilities Found and Fixed](https://patchstack.com/articles/wordpress-7-0-3-released-12-vulnerabilities-found-and-fixed/)
- [CVE-2026-64638: WordPress Pre-Auth XSS Flaw Can Escalate to Remote Code Execution](https://securityonline.info/wordpress-security-update-7-0-3/)
- [WordPress XSS Vulnerability (CVE-2026-64638)](https://blog.reclaimhosting.com/wordpress-xss-vulnerability-cve-2026-64638/)

## Full data

Detection queries (Splunk SPL / Microsoft KQL / Sigma) and IOC values require the Threadlinqs MCP server (Purple tier): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-1933
