The short answer
WordPress released 7.1.2 to fix CVE-2026-87902, a critical path-traversal flaw that lets an unauthenticated request pull a PHP file from outside the active theme. The bug lives in get_page_template(): WordPress builds a template filename from the pagename URL parameter but forgets to run the same traversal check a neighbouring code path already uses. Send double-encoded dots, and the server escapes the theme directory and includes a local PHP file it should never touch. On its own that is local file inclusion; on servers with two common settings it becomes attacker-controlled code execution. If you run a WordPress site — or build them — this is a same-day patch, and hardening the platforms you ship is what a disciplined web development practice does by default.
The scope is what makes it notable: every release from 4.7.0 through 7.1.1 carries the flaw, an omission that sat unnoticed across roughly a decade. The fix is a version bump, but the exposure is a reminder that a single un-validated branch in mature, heavily audited code can quietly undo a security boundary the rest of the codebase enforces.
What the advisory describes
WordPress still powers a large share of the business web, from marketing sites to headless content back ends, which is why a core flaw ripples so widely. On September 22 the project shipped 7.1.2 with a single security fix: CVE-2026-87902, a path-traversal vulnerability in the code that decides which template file renders a given page.
When WordPress resolves a page, get_page_template() in wp-includes/template.php assembles a candidate filename in the form page-{pagename}.php from the pagename query parameter. A neighbouring branch of the same resolver already passes its input through validate_file() to reject ../ traversal — but the pagename branch does not. An attacker sends double-encoded dots (%252e%252e) that survive the first round of sanitisation; when WordPress later calls urldecode(), they become ../, and the resolver walks up out of the theme directory to include a PHP file elsewhere on disk. No account, no login, no plugin required.
Loading a local PHP file runs whatever that file already does, so by itself the bug is a local file inclusion. It escalates to attacker-controlled remote code execution only where two further conditions line up: PHP has register_argc_argv enabled — a default on many older PHP builds and common Docker and cPanel images, though off on PHP 8.5 and later — and a reachable helper such as PEAR's pearcmd.php exists on the server. Where both hold, inclusion becomes execution. The vulnerability was reported privately in July by researcher Robert Ressl, who published an advisory, a proof-of-concept and a pinned test lab when the patch landed.
Why one missing check matters
Path traversal is one of the oldest classes of web bug, and the defence is well understood: never build a filesystem path from user input without validating that it stays inside the directory you intend. WordPress knows this — validate_file() exists precisely for it, and the resolver applies it just a few lines away. CVE-2026-87902 is not a missing concept; it is a single branch that the check was never wired into, and the gap survived a decade of releases because the happy path always worked.
That is the uncomfortable lesson for engineering teams. The dangerous defects in mature software are rarely exotic. They are ordinary safeguards applied to most inputs but quietly skipped on one, in code so familiar that reviewers stop reading it closely. Encoding tricks like double URL-encoding exist specifically to slip past the first layer of sanitisation and re-materialise after a later decode, which is why validation has to happen on the value that actually reaches the filesystem, not the raw request string. A check placed one step too early looks correct and protects nothing.
The conditional nature of the remote code execution deserves the same scrutiny. It is tempting to downgrade a bug because "it is only file inclusion" or "RCE needs an unusual setup." But the conditions here — register_argc_argv enabled, a PEAR helper on disk — are not exotic; they are the defaults on a great many shared, cPanel and containerised hosts. Treating a conditional RCE as low priority is a bet that none of your fleet meets the conditions, and on real infrastructure that bet usually loses.
What it means for US & EU teams
The first implication is inventory. This is a core WordPress bug, not a plugin issue, so it reaches any installation on an affected version regardless of theme or add-ons. Marketing sites, documentation portals, campaign microsites and headless content back ends all count, and those are exactly the properties that live outside the main application's patch cadence and get forgotten. The remediation starts with knowing every WordPress instance your organisation runs, including the ones a marketing team spun up two years ago.
The second implication is server posture, not just the CMS version. Because RCE here depends on PHP configuration and installed packages, two sites on the same WordPress version can carry very different real-world risk. Teams in FinTech, HealthTech and e-commerce — where a compromised web property can expose customer data and trigger GDPR or HIPAA obligations — should check register_argc_argv and the presence of PEAR's pearcmd.php across their hosts, since that is what decides whether a blocked probe or a shell is the outcome.
The third implication is lifecycle discipline for the platforms you did not write. It is easy to patch your own application dependencies on a schedule and treat the CMS behind the brochure site as someone else's problem. This advisory is a reminder that off-the-shelf platforms ship critical fixes too, and that they belong on the same update and monitoring cadence as bespoke code. That is the posture we build into every custom software engagement: the whole stack is inventoried, patched and watched, not just the parts we authored.
What to do now
- Update WordPress immediately. Move to 7.1.2, or the backported patch on your branch (7.0.6, 6.9.9, 6.8.10, 6.7.9, 6.6.9, or 4.7.37). There is no separate workaround from the project — the update is the fix. Confirm the running version after deploying, not just the intended one.
- Check the RCE preconditions. Inspect PHP for
register_argc_argvand disable it inphp.iniwhere you can; look for PEAR and a reachablepearcmd.php; and check whether your active theme has top-levelpage-*folders. These determine whether inclusion can become execution. - Add WAF coverage. Block percent-encoded and double-encoded traversal sequences in the
pagenameparameter at the edge. This buys time on hosts you cannot patch on the same day, but it is a stopgap, not a substitute. - Inventory every WordPress instance. Enumerate all installations across brands, subdomains and campaign sites, and confirm each one is on a patched build. The forgotten site is the one that gets hit.
- Fold the CMS into your patch cadence. Put WordPress — and any other off-the-shelf platform you run — on the same review and monitoring schedule as your application dependencies, so the next core advisory is routine rather than a fire drill.
Frequently asked questions
What is CVE-2026-87902 in WordPress?
It is a critical path-traversal flaw (CVSS 9.2) in how WordPress resolves page templates. get_page_template() in wp-includes/template.php builds a filename from the pagename parameter but, unlike a neighbouring code path, does not run validate_file() to block traversal. An unauthenticated request can therefore make WordPress include a readable local PHP file from outside the active theme, and on servers meeting two further conditions that becomes remote code execution.
Which WordPress versions are affected and fixed?
Every release from 4.7.0 through 7.1.1 is affected. The fix shipped in WordPress 7.1.2 on September 22, 2026, and was backported across the 7.0.x, 6.9.x, 6.8.x, 6.7.x and 6.6.x branches and as far back as 4.7.37. There is no separate workaround, so updating to a patched version is the fix.
When does the flaw become remote code execution?
By itself it is local file inclusion — it runs whatever an existing local PHP file already does. It escalates to attacker-controlled RCE only where PHP has register_argc_argv enabled (a default on many older PHP builds and common Docker and cPanel images, but off on PHP 8.5+) and a reachable file such as PEAR's pearcmd.php is present. Where both hold, inclusion becomes execution.
Is CVE-2026-87902 being exploited?
It was responsibly disclosed by Robert Ressl, who published an advisory, a proof-of-concept and a test lab when the patch landed. Reporting after the September 22 release described reconnaissance within about 18 hours — attackers fingerprinting installations to build target lists rather than mass-deploying RCE. With a public proof-of-concept available and the preconditions common on shared and containerised hosting, patching should be treated as urgent.
What if we cannot update immediately?
Update to a patched build as the real fix, and reduce exposure meanwhile: disable register_argc_argv in php.ini, add WAF rules blocking percent-encoded and double-encoded traversal in the pagename parameter, check the active theme for top-level page-* folders, and verify whether PEAR and pearcmd.php are present. These steps limit risk but do not replace the update.
Sources
WordPress.org — WordPress 7.1.2 security release
The Hacker News — WordPress issues patch for critical flaw that can enable code execution on some servers
Robert Ressl — CVE-2026-87902: critical WordPress file inclusion and conditional RCE (advisory)