Your WordPress site might be handing anonymous visitors a route straight into your server's filesystem, because a security researcher just published a proof of concept for a path traversal flaw in WordPress core, and the worst part is that it needs no login, no account, and no special privileges, since two anonymous POST requests are reportedly enough to walk the template loader out of your theme directory and into files it should never touch.
The flaw is tracked as CVE-2026-87902, it affects WordPress 7.0.2 and earlier across a very wide range of releases, and while the code execution angle depends on your server's configuration, the traversal itself doesn't ask for permission.
What Makes the WordPress Path Traversal Vulnerability So Serious
Path traversal sounds like a file-read bug, and those tend to get filed under "annoying but survivable." That instinct undersells this one.
The defect sits in WordPress's page template resolution, the logic that decides which theme file renders a given page. That logic builds a template name, and under the right conditions, it can be walked outside the theme roots entirely.
Once the loader includes a file it shouldn't, the question shifts from "what can be read" to "what can be run."
Researcher Robert Ressl, publishing through ressl.ch, documented the flaw alongside a public proof-of-concept repository. The technical write-up walks through both stages in detail.
The Technical Details Behind CVE-2026-87902
The core defect is missing path containment in page template resolution. WordPress prepends a fixed page- prefix when constructing the template name, then resolves it against the active theme, and the validation on that path doesn't hold when traversal segments are introduced.
The proof of concept runs in two stages.
- Stage 1 uses the traversal to include a readable local .php file outside the theme roots. When PEAR is present and register_argc_argv is enabled for the web SAPI, /usr/local/lib/php/pearcmd.php acts as a file-write gadget. The config-create command serializes attacker-controlled data, including PHP opening tags, into a writable directory.
- Stage 2 uses the same traversal to include the file PEAR just wrote, which means the embedded PHP executes with the privileges of the web server account.
The important nuance: the WordPress bug is the traversal. PEAR is one environment-dependent way of turning that traversal into code execution, not the root cause.
|
Detail |
Value |
|
CVE |
CVE-2026-87902 |
|
Vulnerability class |
Unauthenticated path traversal leading to local file inclusion |
|
Affected versions |
WordPress 7.0.2 and earlier |
|
Patched in |
7.1.2 and 7.0.6 |
|
Backports |
Every branch down to 4.7.37 |
|
Reported by |
Robert Ressl (ressl.ch) |
|
Public advisory |
GHSA-7hp8-65ch-5whp |
|
Authentication required |
No |
That last row is the one that should set your priority.
Why This Affects Far More Sites Than the Version Number Suggests
Read the patch line again. Backports landed on every branch down to 4.7.37.
WordPress 4.7 shipped in December 2016. The fact that the security team pushed fixes that far back tells you something about how broadly the vulnerable code path is deployed.
If you're running an older branch because a plugin pinned you there, or because nobody's touched the site since a redesign, you're still in scope. The backport exists precisely because that code was still out there.
The Configuration Detail That Decides How Bad This Gets
Not every affected site is exploitable to the same degree, and the difference comes down to server setup.
The code execution path needs a few things to line up:
- A readable PEAR pearcmd.php on the filesystem
- register_argc_argv set to On for the web SAPI
- A writable directory the gadget can target
- A published page using the default template
- A top-level page-* directory in the active theme
That's a real list of preconditions, and plenty of hardened hosts break at least one of them. PEAR is often absent on modern images, and register_argc_argv is commonly Off in production PHP configurations.
But the traversal itself doesn't need any of that. An attacker who can walk the template loader outside your theme roots has a foothold, whether or not they convert it into code execution today.
Configuration that blocks the current PoC isn't a fix. It's a speed bump.
How to Tell If You're Affected
Start with the version, since it's the fastest signal.
WordPress 7.0.2 and earlier sit in the affected range. That includes the 4.7.x line and everything after it, which covers a genuinely enormous install base.
- If you're on 7.1.2, 7.0.6, or any release carrying the backport, you're patched.
- If you're not sure which release you're on, check the dashboard, or query wp core version from WP-CLI.
Then check your exposure surface:
- Is PEAR installed? Look for /usr/local/lib/php/pearcmd.php or the equivalent path on your distribution.
- Is register_argc_argv enabled? Check your PHP configuration for the web SAPI specifically, not just the CLI.
- Do you have published pages on the default template? That's a precondition, and most sites meet it without trying.
- Does your active theme ship a top-level page-* directory? Less common, but worth confirming.
Detection Steps for Security Teams
- Patching is step one. Figuring out whether someone already walked the path is step two.
- Search access logs for POST requests to the site root. The PoC sends anonymous POSTs with page_id and pagename parameters. Legitimate traffic rarely looks like that.
- Look for double-encoded traversal in request bodies. The exploit relies on double encoding so the traversal survives WordPress's sanitizers. Watch for %252F, %252E, or the raw %2F and %2E sequences showing up in POST bodies.
- Hunt for PEAR-related query strings. Any requests that include config-create, pearcmd, or strange +/delimited arguments in the query string need to be immediately investigated.
- Look for any unexpected files in writable directories. The PoC places a created PHP script into a target directory. Look out for unfamiliar .php files in /tmp and any other writable locations.
- Also consider the timestamp on those .php files. An increase in the number of .php files created recently is a signal.
- Watch for outbound or filesystem reads you didn't initiate. The injected payload in the public PoC reads a local file and prints it. Look for requests that return file contents they shouldn't.
Mitigation Beyond Patching
- Patch first, always. Then reduce what an attacker gets if a similar bug lands next year.
- Disable register_argc_argv for the web SAPI. This alone breaks the PEAR gadget path, and very few legitimate applications need it enabled for web requests.
- Remove PEAR if you don't use it. It's a legacy package manager that shows up in a lot of base images by default. If nothing on your stack depends on it, it's pure attack surface.
- Restrict write access on the web server account. The web user should write to uploads and little else. Locking down /tmp and the application root removes the destination the gadget needs.
- Run a web application firewall with traversal rules. It won't catch everything, and it shouldn't be your only defense, but blocking encoded traversal patterns in POST bodies adds friction.
- Keep WordPress core on auto-updates where you can. This bug is exactly the kind that gets patched quietly and sits unapplied for months on sites nobody's watching.
- Audit your plugin and theme inventory. Plugins pinning you to an older core branch are a security liability you should be tracking deliberately.
Why Path Traversal Keeps Coming Back
Traversal is one of the oldest bug classes in web software. It's also one of the most persistent.
The reason is structural. Template resolution, file inclusion, and asset loading all involve building paths from user-influenced input, and every one of those code paths has to get containment right. Miss one, and you've reopened the door.
WordPress has hardened its file handling repeatedly over the years. This advisory shows the pattern isn't finished.
The lesson generalizes past WordPress. Anywhere your application builds a filesystem path from request data, ask what stops ../ from walking somewhere it shouldn't. If the answer is a string replacement on a single encoding pass, the answer is probably wrong.
FAQ
What is CVE-2026-87902?
It's an unauthenticated path traversal flaw in WordPress page template resolution. It can allow local PHP file inclusion, and where the server configuration cooperates, it can lead to PHP code execution.
Which WordPress versions are affected?
WordPress 7.0.2 and earlier. Patches shipped in 7.1.2 and 7.0.6, with backports to every branch down to 4.7.37.
Does exploiting this require authentication?
No. The public proof of concept uses two anonymous POST requests, which makes this materially more dangerous than the authenticated flaws that dominate most advisories.
Does the flaw always lead to remote code execution?
No. Code execution depends on server configuration. It requires a readable PEAR pearcmd.php, register_argc_argv enabled for the web SAPI, and a writable target directory. The traversal itself works without those conditions.
How do I check whether my site was attacked?
Review access logs for anonymous POST requests to the site root carrying page_id and pagename parameters. Look for double-encoded traversal sequences and PEAR-related query strings, then check writable directories for unfamiliar PHP files.
What should I do if I can't patch immediately?
Disable register_argc_argv for the web SAPI, remove PEAR if nothing depends on it, restrict web server write permissions, and add traversal detection at your WAF or reverse proxy. Then patch as soon as you can, because those are mitigations, not fixes.