WordPress Core CVE-2026-87902 Exploited Hours After Patch: Unauthenticated LFI to RCE
A file-inclusion flaw in WordPress core lets unauthenticated attackers reach code execution on sites that meet two common conditions. Patched in 7.1.2; exploited within hours of release.
WordPress shipped an out-of-band security release on 22 September 2026, and attackers were probing for the bug it fixed within hours. CVE-2026-87902 is an unauthenticated file-inclusion flaw in WordPress core that, under conditions many real sites meet, escalates to remote code execution. If you run WordPress anywhere in your estate, this is a same-day patch.
What Happened
WordPress 7.1.2 is a security release that closes a single critical flaw, tracked as CVE-2026-87902 and GitHub advisory GHSA-7hp8-65ch-5whp. The bug carries a CVSS v4.0 base score of 9.2 and is classified as CWE-98, improper control of a filename used in an include statement. Security researcher Robert Ressl reported it privately, and the WordPress security team backported the fix across every branch still receiving updates, from 7.1.2 down through 7.0.6, 6.9.9, 6.8.10, 6.7.9, 6.6.9 and on to 4.7.37.
The defect lives in `get_page_template()`, the function in `wp-includes/template.php` that decides which theme file renders a given page. WordPress assembles a list of candidate template filenames, and one candidate is built from the `pagename` value taken straight out of the request URL. That candidate, of the form `page-{$pagename}.php`, is passed through `urldecode()` but never through `validate_file()`, the check WordPress applies to the other candidates. An attacker who controls `pagename` can therefore walk the path out of the theme directory with encoded traversal sequences and make WordPress include an arbitrary readable PHP file elsewhere on the server. Once PHP includes a file, it runs the code inside it.
File inclusion on its own reads and executes whatever is already on disk. Turning that into attacker-controlled code execution needs a gadget: a local PHP file whose behavior the attacker can steer. The chain seen in the wild uses PEAR's `pearcmd.php`, shipped at paths such as `/usr/local/lib/php/pearcmd.php` and `/usr/share/php/pearcmd.php`, which reads command arguments from the request when the `register_argc_argvregister_argc_argv🛡️A PHP configuration directive, enabled by default, that populates the argument variables from request data. Web applications rarely need it, but leaving it on lets gadgets such as PEAR's command helper read attacker-controlled arguments from the query string, a key link in local-file-inclusion attack chains.` directive is enabled. Attackers call it with `config-create` to write a PHP payload into a world-writable directory like `/tmp`, then include that file to get code execution.
Who Is Affected
Every WordPress core release from 4.7.0 through 7.1.1 contains the vulnerable code. That is nine years of releases, so the exposed population is enormous. Exploitation, however, is conditional, and the two conditions decide whether a given site is actually reachable.
First, the active theme, or its parent, must contain a top-level directory whose name begins with `page-`, such as `page-templates`. That pattern is what lets the crafted `page-{$pagename}.php` candidate resolve at all. The legacy bundled themes Twenty Twelve and Twenty Fourteen ship this layout, as do widely deployed third-party themes including Neve, Hestia and Sydney. Sites on those themes are exposed by default.
Second, a usable gadget file must exist and be readable by the web-server account, and the primary chain needs `register_argc_argv` turned on. That directive defaults to enabled and is present in the official PHP Docker images and in cPanel environments running PHP below 8.5, which describes a large share of managed and containerized hosting. Determining exactly which of your sites meet both conditions is the kind of question addressed in How to Harden PHP So a File-Inclusion Bug Cannot Reach Code Execution.
Technical Analysis
The vulnerabilityVulnerability🛡️A weakness in software, hardware, or processes that can be exploited by attackers to gain unauthorized access or cause harm. is a textbook local file inclusion, and it is worth separating the primitive from the payload. The primitive is the unvalidated `pagename` candidate, a path-traversal issue in the same family covered by How Path TraversalPath Traversal🛡️A web vulnerability (CWE-22) where user-supplied input in a file path escapes the directory the application intended to serve from, typically via parent-directory references, letting an attacker read or write files elsewhere on the server. Bugs Let Attackers Read Files Outside the Web Root; the difference is that WordPress does not merely read the target file, it includes it, so a read primitive becomes an execution primitive. That escalation, and why a benign local file becomes a weapon, is the subject of How a Local File Inclusion Bug Becomes Remote Code Execution Without an Upload.
Patchstack's telemetry shows how quickly the primitive was weaponized. Initial probing hit its honeypotHoneypot🛡️A decoy system deployed to be attacked so defenders can observe exploitation attempts safely. Honeypot networks give early warning that a vulnerability has moved from theoretical to actively exploited, often before official catalogs like CISA KEV confirm it. network at 11:49 UTC on 22 September, the same day the patch shipped; the first attempts to write files through `pearcmd` followed at 15:34 UTC. By 23 September a public Nuclei template and a named proof-of-concept were circulating, and traffic climbed. Independent honeypot operator Previdian recorded 68 exploitation attempts beginning 23 September, sourced from addresses in the United States and Indonesia. The observed requests progressed through recognizable stages: point the inclusion at a harmless core file such as `wp-links-opml.php` to confirm the bug, probe for `pearcmd.php` with `config-show`, then use `config-create` to drop a PHP file into `/tmp` or `/var/tmp`. The traversal payloads used both single and double URL encoding, `%2e%2e` and `%252e%252e`, matching the exact decoding path the patch corrects. Note that reporting on the very first timestamp differs slightly: some outlets frame the first activity as occurring under five hours after release rather than the same-hour figure in Patchstack's timeline. Either way, the window between patch and attack was measured in hours, not days.
The fix does two things. It runs the `pagename`-derived candidate through `validate_file()` like the other candidates, and it adds a helper, `_wp_is_template_path_allowed()`, that requires every resolved template to sit inside an authorized theme location, checked against `$wp_stylesheet_path`, `$wp_template_path` and the `theme-compat` directory. Traversal out of those directories is rejected before any include happens.
Immediate Actions
Update WordPress now. Every current branch has a patched point release, so there is no reason to weigh a major upgrade against staying vulnerable. If you cannot update immediately, reduce exposure by disabling `register_argc_argv`, which breaks the `pearcmd` chain, and by confirming whether your active theme carries a `page-` directory. Neither step fixes the bug; both narrow the blast radiusBlast Radius🛡️The full set of systems, data, and access an attacker can reach after compromising a given asset. Ranking assets by blast radius rather than by how exposed they are pushes high-reach systems like a firewall management console to the top of the priority list. until you patch. At the web edge, block requests that put `%2e%2e` or `%252e%252e` sequences in the `pagename` parameter, and watch for requests referencing `pearcmd`, `config-show` or `config-create`.
Assume that any internet-facing site meeting both conditions may already have been probed. Hunt for unexpected `.php` files in `/tmp` and `/var/tmp`, and for pages that return OPML or RSS content when a normal page URL was requested, a tell-tale sign of a successful test inclusion.
Long-Term Outlook
The speed here is the story. A responsibly disclosed core bug went from patch to public exploitExploit🛡️Code or technique that takes advantage of a vulnerability to cause unintended behavior, such as gaining unauthorized access. tooling in a single day, which means the safety margin many teams assume between disclosure and danger has effectively vanished for popular platforms. Relying on scheduled maintenance windows to apply a fix like this loses the race. The durable answer is twofold: harden the runtime so that even a file-inclusion bug lands on nothing useful, and build a patch-response process fast enough to act the same day, a point developed in Why Auto-Updates Are Not a Substitute for a Patch Response Plan. WordPress powers a large fraction of the web precisely because it is easy to stand up and forget, and that is exactly the property attackers now count on.
Sources
- WordPress 7.1.2 Release, WordPress.org News: https://wordpress.org/news/2026/09/wordpress-7-1-2-release/
- WordPress 7.1.2 Security Release: Unauthenticated LFI to RCE, Patchstack: https://patchstack.com/articles/wordpress-7-1-2-security-release-unauthenticated-lfi-to-rce/
- Attackers Started Probing WordPress Sites Hours After the Patch, Patchstack: https://patchstack.com/articles/cve-2026-87902-attackers-started-probing-wordpress-sites-hours-after-the-patch/
- Attackers Exploit WordPress CVE-2026-87902 Within Hours of Disclosure, The Hacker News: https://thehackernews.com/2026/09/attackers-exploit-wordpress-cve-2026.html
- Critical WordPress Vulnerability Exploited Immediately After Disclosure, SecurityWeek: https://www.securityweek.com/critical-wordpress-vulnerability-exploited-immediately-after-disclosure/
- WordPress 7.1.2 fixes critical unauthenticated path traversal vulnerability, Help Net Security: https://www.helpnetsecurity.com/2026/09/23/cve-2026-87902-wordpress-7-1-2-security-release/
- CVE-2026-87902, NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-87902