# WordPress CVE-2026-64638 Patch: Find and Update Every Vulnerable Site

Source: https://srvscripts.com/guides/wordpress-cve-2026-64638-patch/
Updated: 2026-10-06
Publisher: srvScripts (https://srvscripts.com/)

**Short answer:** CVE-2026-64638 (“XSS2Shell”) is a pre-authentication reflected XSS on the WordPress login screen that can be chained into PHP code execution if a logged-in administrator is tricked into following a link. It is fixed in WordPress 7.0.3 (6 August 2026) and in security releases for older branches such as 6.9.6 and 6.8.7. Hosts should scan every server for `wp-includes/version.php`, list sites below the fixed version for their branch, and update them with `wp core update --minor` run as each site’s owner, ideally straight to the newest release, since later releases fixed more issues.

We ran the audit script, `wp-toolkit --list` and the wp-cli commands on our lab servers (AlmaLinux 9.8 with cPanel & WHM 11.138, and with DirectAdmin 1.712) on 6 October 2026. All lab sites were already on 7.1.2, so the “outdated” example uses a test folder. Vulnerability details were checked against the CVE record, the WordPress release post and independent advisories (linked below).

## What CVE-2026-64638 is

| Item | Detail |
| --- | --- |
| Type | Reflected cross-site scripting (CWE-79) on the login screen, wp-login.php; no login needed to trigger it |
| Severity | CVSS 4.0 base score 8.9 (High) in the CVE record |
| Affected | WordPress before 7.0.3; the CVE record and WordPress say fixes were backported to branches back to 4.7 |
| Fixed in | 7.0.3 (released 6 August 2026); backports include 6.9.6 and 6.8.7 |
| Impact | Under specific conditions involving social engineering and user interaction, the XSS can be chained into remote code execution |
| CVE published | 7 August 2026 |

Advisories differ on two points, so treat both cautiously:

- **Which old versions are really exploitable.** The CVE record and the University of Toronto advisory treat every release from 4.7 to 7.0.2 as affected. Hadrian’s technical write-up says the payload only re-parses into HTML from 6.4 onwards. Patch everything regardless; the backports exist for a reason.

- **Exploitation status.** Early advisories (7 August) reported no public exploit. Wiz’s vulnerability database now lists public proof-of-concept code and reports of exploitation in the wild. Assume it is being used.

The escalation path described by researchers needs an administrator who is logged in (or logs in) and opens an attacker’s page. That is why hosts with many small customer sites are exposed: plenty of site owners will click a convincing link.

## Which version is “fixed” depends on the branch

Do not just flag every site below 7.0.3. A site on the 6.9 branch at 6.9.6 has the fix. A simple version comparison gets this wrong, so the audit below treats patched older branches separately:

| Branch | First fixed release | Notes |
| --- | --- | --- |
| 7.0 | 7.0.3 | Upgrade to the latest 7.0.x or to 7.1.x |
| 6.9 | 6.9.6 | Named by Wiz and the University of Toronto advisory |
| 6.8 | 6.8.7 | Named by Wiz and the University of Toronto advisory |
| Older (down to 4.7) | Branch security release | Check the WordPress release archive for that branch’s number |
| 4.6 and older | No fix | End of life; upgrade or take offline |

WordPress kept shipping security fixes after 7.0.3: 7.0.4 (12 August 2026) contained a security fix, 7.1.1 (17 September) eleven, and 7.1.2 (22 September) a fix for a critical vulnerability. Use 7.0.3 as the floor for this CVE, but update to the current release where you can.

## Step 1: find every WordPress install on the server

Panel tools only see sites they know about. Customers also unpack WordPress by hand into subfolders, staging copies and old directories. Search the disk instead. Our [wordpress-version-audit.sh](/scripts/wordpress-version-audit/) script reads every `wp-includes/version.php`, maps the folder to a domain on cPanel and DirectAdmin, and flags old versions. On our cPanel lab:

```
./wordpress-version-audit.sh --branch-fix 6.9.6,6.8.7
WordPress version audit - panel: cpanel - minimum: 7.0.3 - branch fixes: 6.9.6,6.8.7

DOMAIN             PATH                     VERSION  OWNER  STATUS
site1.example.com  /home/site1/public_html  7.1.2    site1  OK
site2.example.com  /home/site2/public_html  7.1.2    site2  OK
site3.example.com  /home/site3/public_html  7.1.2    site3  OK

Installs found: 3 - outdated (< 7.0.3): 0
```

Against a test folder with one unpatched 7.0.2 copy and one 6.9.6 copy, the same script flagged only the 7.0.2 install and exited with code 1:

```
DOMAIN  PATH                                                 VERSION  OWNER  STATUS
-       /root/srvs-lab/test-hostB/wp-fixture/old-site        7.0.2    root   OUTDATED
-       /root/srvs-lab/test-hostB/wp-fixture/patched-branch  6.9.6    root   BRANCH-FIXED

Installs found: 2 - outdated (< 7.0.3): 1
```

Without the script, a one-liner gives you the raw list:

```
find /home -path /home/virtfs -prune -o -name version.php -path "*/wp-includes/*" -print 2>/dev/null \
  | xargs grep -H "^\$wp_version"
```

### cPanel WP Toolkit view

If WP Toolkit is installed, it lists the installs it manages with their versions. From our cPanel lab:

```
wp-toolkit --list
  ID  Installation Path  Owner ID    State  Hidden  Website URL          Name        Version
   1       /public_html         3  Working   false  http://site1.example.com  Lab site 1    7.1.2
```

Compare its count with the disk scan. Anything the scan finds that WP Toolkit does not is a site nobody is updating.

## Step 2: find out why sites are behind

Minor and security releases normally install themselves. A site still on 7.0.2 weeks later usually has automatic updates turned off. Check the common constants in `wp-config.php`:

```
grep -HnE "WP_AUTO_UPDATE_CORE|AUTOMATIC_UPDATER_DISABLED|DISALLOW_FILE_MODS" \
  /home/*/public_html/wp-config.php /home/*/domains/*/public_html/wp-config.php 2>/dev/null
```

Other causes: files not writable by the PHP user, a broken cron (WordPress checks for updates on page loads or WP-Cron), or a management plugin that pinned the version. Fix the cause or the site will fall behind again on the next release.

## Step 3: update every flagged site

Take a backup of files and database for each site before updating, or confirm last night’s backup is restorable. Updating core is low risk, but very old sites can break on a big jump.

Run wp-cli as the site owner, never as root, so file ownership stays correct. `--minor` updates within the site’s branch (7.0.2 to the latest 7.0.x, 6.9.x to the latest 6.9.x), which is the safest jump:

```
sudo -u bob -- wp core version --path=/home/bob/public_html
sudo -u bob -- wp core update --minor --path=/home/bob/public_html
sudo -u bob -- wp core update-db --path=/home/bob/public_html
```

On our cPanel lab, `sudo -u USER -- wp` failed with `sudo: wp: command not found`, because sudo’s restricted PATH did not include `/usr/local/bin`. Call the binary with its full path instead:

```
sudo -u bob -- /usr/local/bin/php /usr/local/bin/wp core version --path=/home/bob/public_html
```

To update everything the audit flagged, feed its CSV into a loop. Review the list first:

```
./wordpress-version-audit.sh --branch-fix 6.9.6,6.8.7 --only-outdated --csv > /root/wp-outdated.csv
cat /root/wp-outdated.csv
tail -n +2 /root/wp-outdated.csv | while IFS=, read -r domain path version owner status; do
  echo "== $domain ($path) $version"
  sudo -u "$owner" -- /usr/local/bin/php /usr/local/bin/wp core update --minor --path="$path"
