---
schema: 1
kind: vulnerability
title: "CVE-2026-64638 (XSS2Shell) — WordPress Core: a sanitiser disagreement on the login screen chains through DOM clobbering and a JSONP callback into administrator-minted Application Passwords and plugin upload"
headline: "WordPress patches a pre-auth login-screen XSS that chains to code execution, same-day in 7.0.3 with backports to 4.7.34"
summary: >
  CVE-2026-64638 is a pre-authentication reflected XSS on the WordPress login screen, disclosed by
  pwn.ai and patched the same day in WordPress 7.0.3 with backports across every maintained branch
  down to 4.7.34. wp_strip_all_tags() and the later wp_kses_post() tokenizer disagree about whether
  whitespace after an angle bracket starts a tag, so attacker-specified DOM nodes reach a page the
  first function already certified as inert; DOM clobbering plus a JSONP callback then drive a
  logged-in administrator's own browser into approving an Application Password, which uploads a
  plugin whose PHP is web-accessible without activation. Escalation needs one social-engineered
  click by an administrator; the XSS itself needs no authentication. No exploitation reported, and
  this is a distinct chain from the actively exploited WP2Shell.
discovered_at: "2026-08-10T04:41:00Z"
event_date: "2026-08-06"
run_id: 2026-08-10T0411Z-intel
priority: high
immediate_action: null
tags: [vulnerabilities, rce, pre-auth, poc-public, patch-available, identity]
regions: [global, europe, switzerland]
sectors: [public-sector, education, technology]
entities: []
techniques: [T1190, T1204.001, T1098]
affected_products: ["WordPress"]
cves:
  - id: CVE-2026-64638
    cvss: "8.9"
    epss: null
    type: xss
    vector: user-interaction
    auth: pre-auth
    status: [patch-available]
    affected: "4.7.0–4.7.33 through 7.0.0–7.0.2 (24 branch ranges)"
    fixed: "7.0.3 and per-branch backports from 4.7.34"
sources:
  - url: "https://wordpress.org/news/2026/08/wordpress-7-0-3-release/"
    publisher: "WordPress.org"
    date: "2026-08-06"
    role: primary
  - url: "https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-52p2-r8wf-jcrf"
    publisher: "WordPress (GitHub Security Advisory)"
    date: "2026-08-07"
    role: primary
  - url: "https://pwn.ai/blog/xss2shell"
    publisher: "pwn.ai"
    date: "2026-08-06"
    role: corroborating
closed_sources: []
evidence:
  - quote: "Pre-auth reflected cross-site scripting (XSS) on the login screen with potential to lead to PHP code execution reported by the team at pwn.ai."
    publisher: "WordPress.org"
  - quote: "Via a specially crafted malicious third-party website hosted by an attacker, it is possible for this to be escalated to an RCE vulnerability with conditions outside of the attackers control. This requires successful social engineering of and explicit interaction by the target victim."
    publisher: "WordPress (GitHub Security Advisory)"
verification: multi-source
sourcing_note: >
  WordPress's own release announcement and its GitHub Security Advisory are the vendor primary; the
  discovering researcher's write-up is an independent second assessment of the same chain, which is
  what carries credibility to 1.
confidence: high
update_of: null
references: []
deep_dive: false
deep_dive_category: null
org_triage: null
classification:
  reliability: A
  credibility: 1
watchlist_hit: false
actions:
  - "Upgrade WordPress to 7.0.3 or the matching backport for the running branch; where an upgrade cannot land immediately, disabling Application Passwords removes the credential-minting step this chain depends on even if the injection still fires."
migrated_from: null
---

WordPress shipped 7.0.3 on 2026-08-06 fixing CVE-2026-64638, a pre-authentication reflected cross-site scripting flaw on the login screen that the vendor says carries "potential to lead to PHP code execution" ([WordPress.org, 2026-08-06](https://wordpress.org/news/2026/08/wordpress-7-0-3-release/)). The advisory lists 24 separate affected-and-patched branch ranges, from 4.7.0–4.7.33 up to 7.0.0–7.0.2, which is the practical scope statement for anyone maintaining an estate of sites on pinned branches ([WordPress, 2026-08-07](https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-52p2-r8wf-jcrf)).

The root cause is a disagreement between two sanitisers about the same bytes. A failed-login error message runs the submitted username through `wp_strip_all_tags()`, which wraps PHP's `strip_tags()` and only recognises a tag when the angle bracket is immediately followed by a letter; the message later reaches `wp_kses_post()`, WordPress's own tokenizer, which tolerates whitespace between the bracket and the tag name and renders it as a live element ([pwn.ai, 2026-08-06](https://pwn.ai/blog/xss2shell)). The login page therefore ends up carrying real, attacker-specified DOM nodes that the first function had already certified as inert text. From there the chain is a sequence of legitimate mechanisms used in order: a clobbered `ajaxurl` global redirects a script's own request to a same-origin REST route; the REST JSONP callback pattern permits property-chain traversal, so the callback names a method on the opener window and clicks the Application-Password authorization button inside a genuinely logged-in administrator's session; the minted credential then uploads a plugin ZIP, which WordPress extracts into the plugins directory with the nonce and capability checks both passing correctly. The researcher's point is that the extracted PHP is reachable by URL without the plugin ever being activated.

The precondition is worth stating precisely, because it sets the priority: WordPress records that escalation "requires successful social engineering of and explicit interaction by the target victim" — an administrator has to open the attacker's page while logged in. The reflected XSS underneath needs no authentication at all. No party reports exploitation, the flaw was reported on 2026-07-27 and patched on 2026-08-06, and a bounty was paid.

This is **not** the WP2Shell chain this pipeline tracks as actively exploited against Swiss websites. That chain is CVE-2026-63030 with CVE-2026-60137, found by a different team through a REST batch route confusion into pre-authentication SQL injection; the shared "2Shell" branding is coincidence, not a common root cause. Estates that patched for WP2Shell are not covered for this.

Detection, telemetry class first. The discriminating artifact for delivery sits in web and application access logs: a login POST whose username parameter contains an angle bracket followed by whitespace, since that exact sequence is what defeats one sanitiser while surviving the other, and no legitimate username contains it. Downstream, the escalation signature is an Application Password creation event immediately after an authorization-page view with no prior credential-management activity in the session, followed by a plugin upload from the same session. Where REST audit logging exists, requests carrying a JSONP callback parameter are a low-noise hunt query because ordinary WordPress clients rarely use one. **Triage:** the injected elements are themselves on the allowlist, so their presence in a rendered admin notice is not anomalous on its own — the discriminator is that they originate from the login error path, an unauthenticated pre-session context, rather than from authenticated content editing. **Defender takeaway:** patching is the fix and it exists for every maintained branch; for administrators who cannot patch today, turning off Application Passwords breaks the chain at the credential step even though the injection still fires.
