Threat reportVulnerabilityTL-2026-2623
CVE-2026-87902: Critical Unauthenticated Local File Inclusion in WordPress Core (Conditional RCE)
An unauthenticated attacker can abuse WordPress core's get_page_template() page-template resolution to include an arbitrary readable local .php file outside the active theme directory, via a double URL-encoded pagename query parameter that survives sanitization and is later decoded, letting traversal reach files such as PHP's pearcmd.php.
Key facts for WordPress path traversal RCE
| Identifiers | TL-2026-2623, CVE-2026-87902 |
|---|---|
| Severity | CRITICAL |
| CVSS | 9.2 (AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H) |
| Exploitation status | Exploited in the wild |
| Affected products | WordPress WordPress Core |
| Weaknesses (CWE) | CWE-98, CWE-22 |
| Malware | PHP, pear |
| Tools | CVE-2026-87902-Abraxas-Labs.py, cve-2026-87902.py |
| MITRE ATT&CK techniques | T1005 Data from Local System, T1027 Obfuscated Files or Information, T1033 System Owner/User Discovery, T1059 Command and Scripting Interpreter, T1059.004 Command and Scripting Interpreter, T1082 System Information Discovery, T1083 File and Directory Discovery, T1105 Ingress Tool Transfer, T1140 Deobfuscate/Decode Files or Information, T1190 Exploit Public-Facing Application, T1505.003 Web Shell, T1518 Software Discovery and 7 more in the attack flow |
| Motivation | UNKNOWN |
| Detection rules | 9 (1 shown free) |
| Sources | 11 cited sources |
Detection coverage for WordPress path traversal RCE
As of 2026-09-27, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-2623 across Splunk SPL, Microsoft KQL and Sigma, covering 48 indicator(s) of compromise. The whole corpus is readable without an account. Every threat comes with one complete detection in Splunk SPL, Microsoft KQL and Sigma, free for everyone; a free account adds daily TL Creds to unlock the rest. Paid plans add a larger daily allowance, correlation and the MCP server. Threadlinqs MCP server · View plans.
Free detection: WordPress CVE-2026-87902 Double URL-Encoded Pagename Traversal Probe — Exploitation
Detects the unauthenticated exploitation primitive for CVE-2026-87902: requests carrying a double URL-encoded traversal sequence (%252e%252e / %252f) in the pagename query parameter, or requests fingerprinting the vulnerable install by probing wp-links-opml.php, wp-includes/functions.php, or wp-cron.php — the exact target set Patchstack observed in the first in-the-wild probes ~5 hours after the 7.1.2 patch.
- Languages: Splunk SPL, Microsoft KQL, Sigma
- ATT&CK: T1190, T1595.002
- Data sources: web_server_access_logs, waf_logs, w3c_iis_log
- Severity: high
- Confidence: high
Splunk SPL
index=web sourcetype=access_combined
| rex field=uri_query "pagename=(?<pagename_val>[^&]+)"
\`comment("CVE-2026-87902: WordPress literal-'../' sanitizer misses percent-encoded octets; urldecode() inside get_page_template() later reveals the traversal.")\`
| where match(uri_query, "%252[eE]%252[eE]") OR match(uri_query, "%252[fF]") OR match(uri_path, "(?i)(wp-links-opml\.php|wp-cron\.php|wp-includes/functions\.php)")
| eval double_encoded_traversal=if(match(uri_query,"%252[eE]%252[eE]"),1,0)
| eval is_scan_ua=if(match(useragent,"(?i)Go-http-client"),1,0)
| stats count as request_count min(_time) as first_seen max(_time) as last_seen values(uri_path) as targeted_paths values(useragent) as user_agents values(pagename_val) as pagename_values values(double_encoded_traversal) as had_double_encoding by clientip
| where request_count >= 1
| sort -request_countMicrosoft KQL
W3CIISLog
| where TimeGenerated > ago(24h)
// CVE-2026-87902: match either the raw double-encoded traversal payload or the Patchstack-documented fingerprinting target set
| where (csUriQuery has "pagename" and (csUriQuery has "%252e%252e" or csUriQuery has "%252f"))
or csUriStem has_any ("wp-links-opml.php", "wp-cron.php", "wp-includes/functions.php")
| extend DoubleEncodedTraversal = iif(csUriQuery has "%252e%252e", true, false)
| summarize RequestCount=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), TargetPaths=make_set(csUriStem), UserAgents=make_set(csUserAgent) by cIP
| where RequestCount >= 1
| sort by RequestCount descSigma
title: WordPress CVE-2026-87902 Double URL-Encoded Pagename Traversal Probe
id: 8f3a1c2e-4b5d-4e6f-9a1b-2c3d4e5f6a7b
status: experimental
description: Detects unauthenticated exploitation probes for CVE-2026-87902, an LFI in WordPress core's get_page_template() reached via a double URL-encoded pagename parameter, or fingerprinting requests against the specific files Patchstack observed scanners targeting.
references:
- https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-7hp8-65ch-5whp
- https://patchstack.com/articles/cve-2026-87902-attackers-started-probing-wordpress-sites-hours-after-the-patch/
author: AII-Detector — ThreadLinqs Intelligence
date: 2026-09-22
tags:
- attack.reconnaissance
- attack.t1595.002
- attack.initial-access
- attack.t1190
- cve.2026.87902
logsource:
category: webserver
product: nginx
detection:
selection_traversal:
cs-uri-query|contains:
- '%252e%252e'
- '%252E%252E'
selection_targets:
cs-uri-stem|contains:
- 'wp-links-opml.php'
- 'wp-cron.php'
- 'wp-includes/functions.php'
condition: selection_traversal or selection_targets
falsepositives:
- Authorized vulnerability scanners or pentest tooling exercising the same endpoints
- Misconfigured reverse proxies that legitimately double-encode query strings
level: highKnown false positives:
- Authorized vulnerability scanners (Nessus/Qualys) or pentest tooling probing the same endpoints
- Misconfigured reverse proxies or CDNs that legitimately double-encode query strings
- Internal security-team validation traffic re-testing the patch
Tuning notes: Baseline known scanner/proxy source IPs into an allowlist lookup to suppress benign double-encoding traffic; escalate severity when the same source hits multiple PoC-specific paths (wp-links-opml.php, wp-cron.php, wp-includes/functions.php) within a short window, matching the Patchstack cluster pattern.
- WordPress CVE-2026-87902 Double URL-Encoded Pagename Traversal Probe — Exploitation · unlock with TL Creds
- WordPress pearcmd.php Webshell Write & Web-Server-Spawned Shell — Post-Exploitation · unlock with TL Creds
- Post-RCE Web-Server-Process Public Egress & Repeated Sensitive-Path Recon (CVE-2026-87902) · unlock with TL Creds
- WordPress CVE-2026-87902 Double URL-Encoded Pagename Traversal Probe — Exploitation · unlock with TL Creds
- WordPress pearcmd.php Webshell Write & Web-Server-Spawned Shell — Post-Exploitation · unlock with TL Creds
- Post-RCE Web-Server-Process Public Egress & Repeated Sensitive-Path Recon (CVE-2026-87902) · unlock with TL Creds
- WordPress pearcmd.php Webshell Write & Web-Server-Spawned Shell — Post-Exploitation · unlock with TL Creds
- Post-RCE Web-Server-Process Public Egress & Repeated Sensitive-Path Recon (CVE-2026-87902) · unlock with TL Creds
Indicators of compromise for WordPress path traversal RCE
As of 2026-09-27, Threadlinqs Intelligence tracks 48 indicators of compromise for TL-2026-2623.
Sample indicators (3 of 48)
- IP address:
169.58.48[.]193 - URL:
hxxps://raw[.]githubusercontent[.]com/MrG3P5/web-shell/refs/heads/main/uploader.php - IP address:
169.58.48[.]195
Defanged, TLP:CLEAR. Full set of 48 indicators: unlock with TL Creds.
How WordPress path traversal RCE works
On servers where the active theme has a top-level page-* directory and register_argc_argv is enabled (default in official Docker PHP images and common on cPanel/PHP<8.5), the LFI chains into full remote code execution. WordPress 7.1.2 (with backports to 7.0.6, 6.9.9, 6.8.10, 6.7.9, 6.6.9, and 4.7.37) fixes the flaw; multiple public PoCs exist and Patchstack observed the first exploitation probes roughly 5 hours after the patch shipped.
CVE-2026-87902 is a critical (CVSS 9.2, CVSS4 vector AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H; NVD also lists CVSS 3.1 8.1, AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H) path-traversal-to-local-file-inclusion vulnerability (CWE-98, Improper Control of Filename for Include/Require in PHP) in WordPress core versions 4.7.0 through 7.1.1, affecting the decade-plus of releases in that range. The root cause is in wp-includes/template.php inside get_page_template(): when WordPress resolves which template to render for a requested page, it builds a candidate filename by concatenating a caller-influenced value onto a fixed 'page-' prefix and '.php' suffix. A neighboring code branch three lines away already applies a validate_file() containment check before using similar input; the pagename branch does not, an inconsistency in security controls across otherwise-similar operations that Robert Ressl (the discoverer) documented in his write-up and PoC.
The practical exploitation path relies on double URL-encoding: WordPress's request sanitizer strips literal '../' sequences but does not recognize percent-encoded octets (e.g. %252e%252e, i.e. '..' encoded twice), so a payload like 'templates%252f%252e%252e%252f...' survives the initial filter. Later, when get_page_template() calls urldecode() on the pagename value, the encoded traversal sequence is converted into real '../' path segments, and locate_template() concatenates the now-decoded value onto the theme path without re-validating containment. template-loader.php then includes whatever file that traversal resolves to, provided it exists and is readable, without confirming the resolved path stays inside an allowed theme directory. WordPress 7.1.2 closes this two ways: it applies validate_file() to the pagename branch to match the sibling branch, and adds a new _wp_is_template_path_allowed() containment check requiring all resolved template paths to remain inside allowed theme directories -- a defense-in-depth response suggesting broader concern about the template-resolution surface generally.
By itself the flaw is 'only' unauthenticated arbitrary local .php file inclusion (an attacker chooses which readable .php file on the server executes, not what code it runs) -- serious LFI, but not automatically RCE. Four conditions must align for the documented RCE chain: (1) a published, anonymous-accessible Page selectable via page_id with no custom template already assigned, (2) the active theme containing a top-level directory beginning with 'page-' (common in legacy default themes such as Twenty Twelve and Twenty Fourteen, and in themes like Neve, Hestia, and Sydney), (3) a readable .php file reachable via traversal that has exploitable runtime behavior, and (4) that file's environment supporting arbitrary content generation. Ressl's laboratory chain used PHP's bundled PEAR command-line entry point, pearcmd.php, which reads command-line-style arguments out of $_SERVER['argv'] when the PHP ini directive register_argc_argv is enabled -- the default in the official PHP Docker images and common in cPanel hosting running PHP versions below 8.5. A first unauthenticated request abuses pearcmd.php's config-create functionality (invoked via a crafted 'pagename' that traversal-includes it, with query-string content acting as PEAR CLI arguments) to write a second, attacker-controlled PHP file to a writable temp directory; a second request re-exploits the same LFI to include that generated file, achieving code execution as the web server's account (www-data in testing). Ressl explicitly cautions that his evidence 'does not establish' that every default WordPress installation is exploitable to full RCE -- the chain is environment-dependent (PEAR availability, register_argc_argv, writable temp paths), not a WordPress-specific guarantee -- but the underlying unauthenticated LFI is present in every affected core version regardless of those conditions.
WordPress disclosed and patched the issue on 2026-09-22. Independent of the vendor advisory, Robert Ressl published a detailed technical write-up and a Docker-based reproduction lab (pinned to wordpress:7.0.2-php8.3-apache with register_argc_argv deliberately enabled) at ressl.ch, and at least two further public PoC repositories (GitHub user abraxas, and a listing by 'pwnVader' indexed on Sploitus) appeared the same day, each independently demonstrating the traversal-to-inclusion primitive with slightly different encoding depth and target-file choices. Patchstack's WAF telemetry recorded the first exploitation probes at 2026-09-22T17:44Z -- under five hours after the WordPress.org patch release -- from a small, concentrated cluster of source addresses (two neighboring IPv4 hosts plus supplementary IPv6 traffic) using automated Go-http-client requests with double-encoded traversal against wp-links-opml.php, wp-includes/functions.php, and wp-cron.php as detection targets; as of the most recent telemetry (2026-09-22T19:51Z) this activity remained reconnaissance/fingerprinting rather than confirmed payload delivery, and the CVE had not yet been added to the CISA KEV catalog. Given WordPress's ~43% share of the web and the fact that a large majority of live installs lag the latest release, and the unusually deep backport (patches were issued all the way back to the 4.7 branch, first released in 2016), the vendor's own patch scope signals broad recognized exposure across long-lived, infrequently-updated WordPress deployments.
MITRE ATT&CK techniques by tactic:
Collection
Defense Evasion
T1027 Obfuscated Files or Information; T1140 Deobfuscate/Decode Files or Information
Discovery
T1033 System Owner/User Discovery; T1082 System Information Discovery; T1083 File and Directory Discovery; T1518 Software Discovery
Execution
T1059 Command and Scripting Interpreter; T1059.004 Command and Scripting Interpreter
Command and Control
Initial Access
T1190 Exploit Public-Facing Application
Persistence
Credential Access
T1552.001 Unsecured Credentials
Resource Development
T1588.002 Obtain Capabilities: Tool; T1588.005 Exploits; T1588.006 Obtain Capabilities; T1608.001 Stage Capabilities: Upload Malware
Reconnaissance
Remediation for WordPress path traversal RCE
Patches
- WordPress 7.1.2
- WordPress 7.0.6
- WordPress 6.9.9
- WordPress 6.8.10
- WordPress 6.7.9
- WordPress 6.6.9
- WordPress 4.7.37
Immediate actions
- Update WordPress core to 7.1.2 (7.1 branch), 7.0.6 (7.0 branch), 6.9.9, 6.8.10, 6.7.9, 6.6.9, or 4.7.37 (legacy branches down to 4.7) as applicable to your installed line.
- If immediate patching is not possible, check whether the active theme contains a top-level directory whose name begins with 'page-' (e.g. page-templates/) and treat any such site as high exposure pending the update.
- Disable register_argc_argv in php.ini on any internet-facing PHP host where it is not explicitly required; it is on by default in the official PHP Docker images and on many cPanel/PHP<8.5 hosting stacks.
- Remove or restrict web access to unused PEAR command-line entry points such as pearcmd.php on production web servers.
- Deploy a WAF/edge rule blocking percent-encoded traversal sequences (e.g. %252e%252e, %252f) in the pagename query parameter, which Patchstack identifies as a reliable detection/blocking signal for this specific flaw.
Workarounds
- Block or rewrite requests containing percent-encoded traversal sequences in the pagename query parameter at the WAF/reverse-proxy layer.
- Disable register_argc_argv and remove web-readable pearcmd.php to break the documented RCE escalation path even if the LFI itself cannot be immediately patched.
Longer-term hardening
- Restrict the PHP process account's filesystem read access and remove write access to temp/upload directories where not required, to break the write-then-include RCE chain even if a future LFI-class bug is found.
- Monitor WordPress core, theme, and plugin update channels and reduce time-to-patch for internet-facing installs, given the observed <5 hour window between patch release and first exploitation probes.
- Audit legacy/default themes (Twenty Twelve, Twenty Fourteen, Neve, Hestia, Sydney, and any others with page-prefixed top-level directories) across managed WordPress fleets and prioritize their remediation.
Affected and fixed versions
- WordPress — WordPress Core
Vulnerable versions: 4.7.0-7.1.1
Fixed in: 7.1.2; 7.0.6; 6.9.9; 6.8.10; 6.7.9; 6.6.9; 4.7.37
Timeline of WordPress path traversal RCE
Last updated · 3 updates · revalidated 3× · latest source
- locked-ioc-42 privately discloses CVE-2026-87902 to the WordPress security team via HackerOne, ahead of the September 2026 public patch.
- WordPress acknowledges locked-ioc-42's HackerOne report of the page-template path-traversal vulnerability.
- WordPress informs the reporter that a fix is planned ahead of the 2026-09-22 security release.
- locked-ioc-45 observes the first pearcmd config-show probes (testing PEAR reachability) at 15:34 UTC, preceding later config-create file-write attempts.
- locked-ioc-45 reports blocking the first exploitation attempt at 11:49 UTC, earlier than the previously recorded 17:44 UTC first-probe timestamp.
- As of publication, CVE-2026-87902 has not been added to the CISA Known Exploited Vulnerabilities catalog.
- locked-ioc-45's most recent recorded activity at time of reporting (19:51 UTC) shows continued reconnaissance/fingerprinting probes against wp-links-opml.php, wp-includes/functions.php, and wp-cron.php, with no confirmed successful payload delivery yet observed in their telemetry.
- locked-ioc-45's WAF telemetry records the first in-the-wild probing/exploitation attempts at 17:44 UTC, under five hours after the patch's release, from a small cluster of source addresses (locked-ioc-35, locked-ioc-36, and IPv6 locked-ioc-25) using automated Go-http-client requests with double-URL-encoded traversal payloads.
- The Hacker News publishes coverage of the WordPress patch and the conditional-RCE flaw, surfacing it to a broad audience of administrators.
- A third independent exploit, authored by 'locked-ioc-46', is indexed on the Sploitus exploit-aggregation site, using an empty-body POST detection technique against wp-includes/version.php.
- Independent public proof-of-concept exploit code is published on GitHub by user abraxas (CVE-2026-87902 repository) with its own reproduction script and lab fixture.
- locked-ioc-42 publishes a detailed technical write-up and a Docker-based reproduction lab (pinned wordpress:7.0.2-php8.3-apache image) at ressl.ch demonstrating the full LFI-to-RCE chain via pearcmd.php.
- WordPress publishes GitHub Security Advisory GHSA-7hp8-65ch-5whp detailing the flaw and patched version list.
- CVE-2026-87902 is published in the NVD at 17:17:28 UTC with a CVSS 3.1 base score of 8.1 (WordPress/GHSA separately rate it 9.2 under CVSS 4.0).
- WordPress releases 7.1.2 and backported fixes (7.0.6, 6.9.9, 6.8.10, 6.7.9, 6.6.9, and 4.7.37) closing CVE-2026-87902 by adding validate_file() checks and a new _wp_is_template_path_allowed() containment function.
- locked-ioc-45 reports exploitation volume increased more than tenfold as public PoC and Nuclei scanning tooling circulated, with attackers now writing executable PHP payloads to locked-ioc-48 and locked-ioc-47 via pearcmd config-create; BleepingComputer publishes escalation coverage.
- Security researchers (SecurityArsenal, Security Affairs) publish detailed detection and remediation guidance for CVE-2026-87902, including web-request signatures, filesystem IOCs, and process-behavior indicators for defenders.
- CISA adds CVE-2026-87902 to its Known Exploited Vulnerabilities catalog based on confirmed evidence of active exploitation.
- CISA Binding Operational Directive 26-04 remediation deadline for FCEB agencies to apply the WordPress fix and complete forensic triage for prior compromise.
Update history
- 2026-09-27 — CVE-2026-87902: WordPress Core Remote File Inclusion Vulnerability Added to CISA KEV Catalog: What changed No severity/exploitability/status/CVSS escalation (already CRITICAL/ACTIVE/9.2 in both records); the material change is regulatory: CISA added CVE-2026-87902 to the KEV catalog on 2026-09-25 with a BOD 26-04 remediation deadlin
- 2026-09-27 — WordPress Core CVE-2026-87902 Unauthenticated Path Traversal in get_page_template() to Conditional RCE Actively Exploited: What changed No field escalation needed — severity (CRITICAL) and exploitability (ACTIVE) were already at their ceiling. What changed is the observed attack stage: reconnaissance-only probing (as of the existing record's 19:51 UTC snapshot)
- 2026-09-27 — CVE-2026-87902: Critical WordPress Core Path Traversal / Local PHP File Inclusion Enabling Unauthenticated Conditional RCE: New indicators (7) Indicator values are withheld at this access level. New CVEs (0) None — same CVE-2026-87902. New detections (0) CWE-22 (Path Traversal) added alongside existing CWE-98 classification. New MITRE (5) 5 additional ATT&CK tec
Sources cited for WordPress path traversal RCE
- Unauthenticated path traversal in page-template resolution leading to conditional RCE (GHSA-7hp8-65ch-5whp) GitHub · Advisory · 2026-09-22
- NVD - CVE-2026-87902 Detail NVD (NIST) · Advisory · 2026-09-22
- CVE-2026-87902 WordPress technical write-up and PoC lab ressl.ch · Research · 2026-09-22
- ressl/cve-2026-87902-poc: PoC for unauthenticated path traversal in WordPress page-template resolution GitHub · Proof of concept · 2026-09-22
- abraxas/CVE-2026-87902: Unauthenticated Local File Inclusion (conditional RCE) GitHub · Proof of concept · 2026-09-22
- pwnVader exploit listing for CVE-2026-87902 sploitus.com · Proof of concept · 2026-09-22
- CVE-2026-87902: Attackers Started Probing WordPress Sites Hours After the Patch patchstack.com · Blog · 2026-09-22
- WordPress 7.1.2 Security Release: Unauthenticated LFI to RCE patchstack.com · Blog · 2026-09-22
- CVE-2026-87902: WordPress RCE Flaw Already Exploited byteiota.com · Blog · 2026-09-22
- CVE-2026-87902: Critical WordPress RCE Flaw Fixed in Version 7.1.2 securityonline.info · Blog · 2026-09-22
- WordPress Issues Patch for Critical Flaw That Can Enable Code Execution on Some Servers The Hacker News · News · 2026-09-22
Previous and next in vulnerability
Drafted by the Threadlinqs research pipeline from 11 sources; published ; last updated .