Back to Intelligence

CVE-2026-87902: WordPress Unauthenticated Path Traversal Leads to Critical Code Execution — Fedora 43 Detection and Remediation Guide

SA
Security Arsenal Team
October 3, 2026
11 min read

The Fedora Project has shipped an emergency update for WordPress on Fedora 43, pulling in WordPress 6.9.9 — a dedicated security release that patches CVE-2026-87902, an unauthenticated path traversal vulnerability in WordPress core's page-template resolution logic that can be chained into critical remote code execution under specific conditions. The advisory (Fedora FEDORA-2026-5c9d8e41a9) packages the upstream WordPress 6.9.9 security release, which follows the 6.9.8 security release in rapid succession — a signal that the WordPress security team is treating this class of flaw with maximum urgency.

Let me be direct: unauthenticated, remotely reachable path traversal in the world's most-deployed CMS is about as bad as it gets from an exposure standpoint. WordPress powers well over 40% of the public web. Any flaw in core template resolution is reachable before authentication, before plugin logic, and often before WAF rules that administrators assume are protecting them. When that traversal can be conditioned into arbitrary code execution — by resolving a template from an attacker-controlled path, such as a file uploaded through a legitimate media or avatar endpoint — you have a pre-auth RCE chain.

If you run WordPress on Fedora 43 (or any distribution consuming upstream WordPress), treat this as a patch-now event.

Technical Analysis

Affected Products and Versions

  • Product: WordPress core
  • Fixed version: WordPress 6.9.9 (security release)
  • Prior security release: WordPress 6.9.8
  • Affected versions: WordPress releases prior to 6.9.9 containing the vulnerable page-template resolution code path
  • Distribution: Fedora 43, package update wordpress (advisory FEDORA-2026-5c9d8e41a9, published via linuxsecurity.com)
  • Note: Sites using WordPress's automatic background updates for security releases should already be on 6.9.9 — verify, don't assume.

The Vulnerability: CVE-2026-87902

Class: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory — Path Traversal), chained to code execution

Attack vector: Network, unauthenticated

The flaw resides in how WordPress resolves page templates. When WordPress renders a page, it determines which PHP template file to load based on the request — via the template hierarchy and, in certain code paths, template hints derived from user-controllable input (query parameters, request URIs, or block-theme template references). The vulnerable code path fails to adequately canonicalize and constrain the resolved template path to the theme directory.

From a defender's perspective, the exploitation chain looks like this:

  1. Traversal primitive: An unauthenticated attacker crafts a request that injects directory traversal sequences (../, URL-encoded variants %2e%2e%2f, %252e, or path-normalization bypasses such as ....//) into the template resolution input, causing WordPress to resolve a PHP template outside the intended theme directory.
  2. Conditional code execution: The traversal alone yields file inclusion. Escalation to code execution is conditional — it requires the attacker to control the contents of a file reachable by the traversal. The classic primitive is a PHP file planted via a legitimate upload channel (media library on misconfigured sites, avatar/comment attachment endpoints, a writable plugin upload path, or a second plugin vulnerability), or abuse of attacker-controllable files such as log/session content on shared hosting.
  3. Execution: WordPress includes the resolved template file within the PHP interpreter context, executing attacker-controlled code as the web server user (apache/nginx/php-fpm), which typically has read access to wp-config.php — meaning database credentials, authentication keys, and salts are immediately compromised.

Post-exploitation, expect webshell drops in wp-content/uploads/, rogue administrator account creation, malicious plugin/theme installation for persistence, and database content injection (SEO spam, redirect kits, credit-card skimmers on WooCommerce).

Exploitation Status

The WordPress security team shipped this as an out-of-cycle security release, which historically correlates with either reported exploitation or a vulnerability simple enough to weaponize that mass exploitation is expected within days of disclosure. Path traversal in a pre-auth code path of WordPress core is trivially scannable — automated probes for traversal patterns against WordPress sites typically begin within 24–48 hours of a public advisory. Treat this as exploitation imminent/expected, patch on an emergency change window, and hunt retroactively across logs from the disclosure date backward.

Detection & Response

This is a technical threat. The detections below target the three most reliable observables: (1) traversal strings in HTTP requests to WordPress template-relevant endpoints, (2) the web server PHP process spawning child processes or writing PHP files into upload directories, and (3) webshell artifacts on disk.

Sigma Rules

YAML
---
title: WordPress CVE-2026-87902 Path Traversal in Template Resolution Request
id: 3f8c1a42-7b9d-4e51-a6c2-9d4e5f6a7b8c
status: experimental
description: Detects HTTP requests containing directory traversal sequences targeting WordPress template-resolution parameters or URIs, consistent with exploitation of CVE-2026-87902 (unauthenticated path traversal in page-template resolution).
references:
  - https://linuxsecurity.com/advisories/fedora/fedora-43-wordpress-2026-5c9d8e41a9
  - https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/04/10
tags:
  - attack.initial_access
  - attack.t1190
logsource:
  category: webserver
detection:
  selection_uri:
    cs-uri-query|contains:
      - '../'
      - '..\\'
      - '%2e%2e%2f'
      - '%2e%2e\\'
      - '%252e%252e'
      - '....//'
  selection_wp:
    cs-uri-query|contains:
      - 'template'
      - 'pagename'
      - 'page_id'
      - 'wp-content/themes'
  condition: selection_uri and selection_wp
falsepositives:
  - Legitimate theme/plugin developers testing template paths
  - Broken internal links with malformed relative paths
level: high
---
title: Web Server Process Spawning Shell or Command Interpreter
id: 8a2d4e61-3c7b-4f92-b1d5-6e8a9c0d1e2f
status: experimental
description: Detects Apache, Nginx, or PHP-FPM worker processes spawning command shells or interpreters — a strong post-exploitation indicator following WordPress code execution such as CVE-2026-87902 template-include RCE.
references:
  - https://linuxsecurity.com/advisories/fedora/fedora-43-wordpress-2026-5c9d8e41a9
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/04/10
tags:
  - attack.execution
  - attack.t1059.004
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/httpd'
      - '/apache2'
      - '/nginx'
      - '/php-fpm'
      - '/php-cgi'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/zsh'
      - '/curl'
      - '/wget'
      - '/python'
      - '/python3'
      - '/perl'
      - '/nc'
      - '/ncat'
      - '/base64'
  condition: selection_parent and selection_child
falsepositives:
  - Rare legitimate plugin functionality invoking system commands (e.g., image processing, backups) — investigate parent-child context before dismissing
level: critical
---
title: PHP File Written to WordPress Uploads Directory
id: c5e7f2a9-1d4b-48e6-93a1-2b3c4d5e6f70
status: experimental
description: Detects creation of PHP files inside wp-content/uploads — a canonical webshell drop location following WordPress RCE exploitation such as CVE-2026-87902. The uploads tree should never legitimately contain executable PHP.
references:
  - https://linuxsecurity.com/advisories/fedora/fedora-43-wordpress-2026-5c9d8e41a9
  - https://attack.mitre.org/techniques/T1505/003/
author: Security Arsenal
date: 2026/04/10
tags:
  - attack.persistence
  - attack.t1505.003
logsource:
  category: file_event
  product: linux
detection:
  selection:
    TargetFilename|contains: '/wp-content/uploads/'
    TargetFilename|endswith:
      - '.php'
      - '.phtml'
      - '.php5'
      - '.php7'
      - '.phar'
  condition: selection
falsepositives:
  - Extremely rare; some broken plugins write PHP into uploads — any hit warrants triage
level: critical

KQL — Microsoft Sentinel / Defender

These queries assume web server access logs (Apache/Nginx) are ingested via Syslog/CEF, or that WordPress hosts are onboarded to Defender for Endpoint. Hunt retroactively from the disclosure date backward at least 14 days.

KQL — Microsoft Sentinel / Defender
// Hunt 1: Traversal sequences in requests to WordPress template parameters (Apache/Nginx via Syslog ingestion)
Syslog
| where TimeGenerated > ago(14d)
| where ProcessName in~ ("httpd", "apache2", "nginx", "php-fpm") or Computer has "web"
| extend RawMsg = tostring(SyslogMessage)
| where RawMsg has_any ("../", "%2e%2e", "%252e", "....//")
| where RawMsg has_any ("template", "pagename", "page_id", "wp-content/themes", "index.php")
| extend HttpRequest = extract(@"GET ([^ ]+)", 1, RawMsg)
| summarize RequestCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
    by Computer, SourceIP = HostIP, HttpRequest
| order by RequestCount desc
;
// Hunt 2: Web server process spawning shell/interpreter child processes (Defender for Endpoint)
DeviceProcessEvents
| where TimeGenerated > ago(14d)
| where InitiatingProcessFileName in~ ("httpd", "apache2", "nginx", "php-fpm", "php-cgi")
| where FileName in~ ("sh", "bash", "dash", "curl", "wget", "python3", "perl", "nc", "ncat", "base64")
| project TimeGenerated, DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine, AccountName, InitiatingProcessCommandLine
| order by TimeGenerated desc
;
// Hunt 3: PHP files created under wp-content/uploads (webshell staging)
DeviceFileEvents
| where TimeGenerated > ago(14d)
| where FolderPath has "wp-content/uploads"
| where FileName endswith ".php" or FileName endswith ".phtml" or FileName endswith ".phar"
| project TimeGenerated, DeviceName, FolderPath, FileName, InitiatingProcessFileName, InitiatingProcessCommandLine, SHA256
| order by TimeGenerated desc

Velociraptor VQL

Use this artifact for rapid triage across suspected WordPress hosts: enumerate PHP webshell candidates in uploads, then correlate with web-server child processes.

VQL — Velociraptor
-- WordPress CVE-2026-87902 triage: PHP files in uploads + suspicious web-server child processes
-- Part 1: PHP/executable files planted under wp-content/uploads (webshell candidates)
SELECT FullPath, Size, Mtime, Ctime
FROM glob(globs='/var/www/**/wp-content/uploads/**/*.php')
WHERE Mtime > now() - 1209600  -- last 14 days
ORDER BY Mtime DESC

-- Part 2: Web server processes with shell/interpreter children (live RCE indicator)
SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(/bin/(ba|da|z)?sh|curl|wget|python|perl|ncat|base64)'
   OR Name =~ '^(sh|bash|dash|nc|ncat)$'

-- Part 3: Recently modified files in theme directories (template overwrite persistence)
SELECT FullPath, Size, Mtime
FROM glob(globs='/var/www/**/wp-content/themes/**/*.php')
WHERE Mtime > now() - 1209600
ORDER BY Mtime DESC

Remediation & Verification Script (Bash — Fedora 43)

Bash / Shell
#!/usr/bin/env bash
# CVE-2026-87902 remediation & verification — Fedora 43 WordPress
# Run as root. Stops on error; prints verification evidence for change records.
set -euo pipefail

echo "=== [1/5] Current WordPress package version ==="
rpm -q wordpress || echo "wordpress package not installed via rpm — check manual installs under /var/www"

echo "=== [2/5] Applying Fedora 43 security update (FEDORA-2026-5c9d8e41a9) ==="
dnf -y upgrade wordpress --advisory=FEDORA-2026-5c9d8e41a9 || dnf -y upgrade wordpress

echo "=== [3/5] Verifying patched version (must be 6.9.9 or later) ==="
WP_VER=$(rpm -q --qf '%{VERSION}' wordpress 2>/dev/null || echo "0")
echo "Installed WordPress version: ${WP_VER}"
if [[ "$(printf '%s\n' "6.9.9" "${WP_VER}" | sort -V | head -n1)" != "6.9.9" ]]; then
  echo "[!] WARNING: WordPress version ${WP_VER} is BELOW 6.9.9 — still vulnerable to CVE-2026-87902"
fi
# For non-rpm installs, check version.php directly:
# grep -h '\$wp_version' /var/www/*/wp-includes/version.php

echo "=== [4/5] Hunting for webshell artifacts in uploads (should return empty) ==="
find /var/www -type d -path '*wp-content/uploads*' -exec find {} -type f \( -name '*.php' -o -name '*.phtml' -o -name '*.phar' \) -mtime -14 -ls \; 2>/dev/null || true

echo "=== [5/5] Hunting logs for traversal probes against template parameters ==="
journalctl -u httpd -u nginx --since "14 days ago" 2>/dev/null | grep -Ei '(\.\./|%2e%2e|%252e|\.\.\.\.//).*(template|pagename|page_id)' | tail -50 || \
grep -Ehi '(\.\./|%2e%2e|%252e|\.\.\.\.//).*(template|pagename|page_id)' /var/log/httpd/*access*log /var/log/nginx/*access*log 2>/dev/null | tail -50 || echo "No matches — retain logs for IR timeline anyway"

echo "=== Hardening reminder: disable PHP execution in uploads ==="
cat <<'EOF'
# Add to your Apache config / .htaccess inside wp-content/uploads:
#   <FilesMatch "\.(php|phtml|phar)$">
#     Require all denied
#   </FilesMatch>
# For nginx, add a location block returning 403 for PHP under /wp-content/uploads/.
EOF

Remediation

  1. Patch immediately. On Fedora 43: sudo dnf upgrade wordpress --advisory=FEDORA-2026-5c9d8e41a9. Confirm the installed version is WordPress 6.9.9 or later. For sites tracking upstream directly, update via the WordPress admin dashboard or wp core update. Do not rely on background auto-updates without verification — check wp-includes/version.php.
  2. Verify every site, not just production. Staging, dev, and forgotten marketing microsites running WordPress are frequently the initial entry point. Inventory all WordPress instances on your infrastructure, including containerized and LEMP/LAMP-stack deployments outside package management.
  3. Block PHP execution in wp-content/uploads. This neutralizes the most common conditional-RCE escalation path (planted PHP file + traversal include). Enforce it at the web server layer as shown in the script above — this is a durable hardening control, not just a CVE workaround.
  4. Hunt retroactively. Exploitation of pre-auth traversal primitives scales fast. Run the KQL hunts above across at least the last 14 days of web logs. Any traversal hit against template parameters followed within minutes by a PHP write to uploads is a confirmed compromise — invoke your IR plan, isolate the host, rotate wp-config.php credentials and all authentication keys/salts (rotating salts force-invalidates all sessions and cookies), and audit administrator accounts and installed plugins/themes for persistence.
  5. WAF as a compensating control, not a fix. If patching must be scheduled, deploy virtual patching: block requests containing traversal sequences (../, %2e%2e, double-encoded variants) in query strings against WordPress endpoints. Understand that encoding-bypass variants make WAF rules brittle — they buy time, they do not close the hole.
  6. Reduce post-exploitation blast radius. Ensure the PHP-FPM/Apache user has read-only access to the WordPress core tree (ownership split: root owns code, web user owns only wp-content/uploads), restrict ALLOW_UNFILTERED_UPLOADS, and enforce least-privilege database credentials.

References: Fedora advisory FEDORA-2026-5c9d8e41a9 and the WordPress 6.9.9 Security Release notes on wordpress.org/news. Monitor CISA KEV for addition of CVE-2026-87902 — WordPress core RCE flaws are historically cataloged quickly once exploitation is confirmed.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.