Like graffiti on a maintenance hatch that only matters if an admin opens it from the wrong side
CVE-2026-6735 is an XSS bug in the PHP-FPM status endpoint, not in ordinary PHP page rendering. Upstream affected ranges are PHP 8.2.x before 8.2.31, 8.3.x before 8.3.31, 8.4.x before 8.4.21, and 8.5.x before 8.5.6; the vulnerable behavior is that attacker-controlled request data can be reflected into the status page, where it executes if someone views the HTML status output in a browser.
The vendor's MEDIUM 6.1 is defensible in a lab, but a little generous in real enterprise conditions. The chain needs pm.status_path enabled, the status page reachable, a victim to open the HTML view, and some same-origin value to steal or abuse; that is a long way from pre-auth RCE, and most mature shops already keep this page internal-only or disabled.
4 steps from start to impact.
Find a reachable PHP-FPM status page
httpx, nuclei, or plain curl against paths like /fpm-status or custom pm.status_path values. The goal is not PHP code execution; it is simply locating a status endpoint that the web server exposes to a browser.php-fpmis deployedpm.status_pathis enabled in at least one pool- the web server routes requests to that status path
- the attacker can reach the endpoint from their network position
- The PHP manual explicitly recommends restricting the page to internal requests or known IPs
- many deployments proxy the status page only via localhost or a Unix domain socket-backed local route
- custom path names reduce commodity scanning success
/fpm-status, /status, or ?full.Seed a malicious request URI
Burp Suite or curl, the attacker sends a crafted HTTP request whose URL contains a JavaScript payload. Because the bug is improper sanitization of user data in the status output, that request can become the bait an operator later renders in the status page.- the attacker can send at least one HTTP request through the same PHP-FPM pool
- the vulnerable branch is running
- the request metadata is surfaced in the status page view
- if the request hits a different pool than the monitored one, the payload may never appear
- if the status page is viewed in text, JSON, XML, or OpenMetrics workflows, the browser-execution angle disappears
- URL normalization or upstream filtering may mangle simple payloads
<script>, event-handler strings, or suspicious URI characters in web access logs and reverse-proxy telemetry.Wait for a human to open the HTML status view
/fpm-status?html&full. This is classic browser-side execution: no human view, no exploit outcome.- a human with browser access views the status page
- the page is rendered as HTML
- the victim browser can execute the injected payload
- many monitoring stacks consume machine-readable output rather than HTML
- admins may rarely open the status page interactively
- some teams segregate monitoring on a separate host or origin, limiting useful browser context
Abuse the browser session on that origin
BeEF, but the impact stays bounded by the browser session and origin policy.- the victim session has something valuable in that origin context
- cookies are readable or actions are CSRF-able from the page origin
- the endpoint shares an origin with something sensitive
- this is not server-side execution
- if the status endpoint is on a separate vhost or internal-only hostname, cookie and application blast radius shrinks hard
- HttpOnly cookies and tight CSP can reduce post-XSS value
The supporting signals.
| In-the-wild status | No authoritative evidence of active exploitation located in vendor, NVD, or CISA KEV sources. This aligns with the supplied EPSS 0.00046 and the absence of KEV listing. |
|---|---|
| Proof-of-concept availability | No authoritative public PoC was validated from upstream PHP or GitHub advisory material. The public patch trail is enough for a competent researcher to reproduce, but this is not currently a commodity exploit story. |
| EPSS | 0.00046 from the provided intel block; that is extremely low exploitation probability pressure compared with bugs that move patch queues. |
| KEV status | Not listed in CISA's Known Exploited Vulnerabilities catalog. |
| CVSS vector reality check | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N correctly captures UI:R and no server-side availability impact. In practice, the real penalty is even harsher because reachability depends on an intentionally enabled monitoring endpoint. |
| Affected versions | Upstream branches affected: 8.2.x < 8.2.31, 8.3.x < 8.3.31, 8.4.x < 8.4.21, 8.5.x < 8.5.6. |
| Fixed versions | Upstream fixed in PHP 8.2.31, 8.3.31, 8.4.21, and 8.5.6, released on 2026-05-07. |
| Distro backports | Do not key only on upstream version strings in distro environments. Ubuntu shipped fixes via package backports in USN-8336-1 and Debian LTS addressed the issue in php7.4 7.4.33-1+deb11u11, even though those versions do not look like upstream 8.x. |
| Exposure population | No reliable internet-scale census for this exact path was found. My assessment is low exposed population by design because PHP's own manual says the status page should be restricted to internal requests or known client IPs; that is an inference from official deployment guidance, not a measured internet-wide count. |
| Disclosure and attribution | NVD shows published 2026-05-10 with PHP Group as source. Upstream changelog and NVD do not clearly credit an external reporting researcher. |
noisgate verdict.
The decisive factor is reachability friction: this bug only matters if a deliberately enabled PHP-FPM status page is exposed to a browser-accessible user path. Even then, the impact is browser-bound XSS on a monitoring endpoint, not server compromise, and there is no current exploitation pressure pushing it up the queue.
Why this verdict
- Start from the vendor 6.1 baseline, then subtract for endpoint exposure: exploitation begins only if
pm.status_pathis enabled and reachable; plenty of fleets never expose that path beyond localhost or monitoring IPs. - Subtract again for attacker workflow friction: the bug needs an operator to open the HTML status page in a browser. JSON, XML, text, and OpenMetrics consumers do not turn this into active script execution.
- Subtract for blast radius: this is XSS in a status/monitoring surface, so the payoff is limited to the victim browser's same-origin context rather than arbitrary server execution or tenant-wide takeover.
- Keep it above IGNORE because the chain is still real: if you expose
/fpm-statuson the same origin as sensitive apps, a crafted URI plus an admin browser session can become useful session abuse. - No threat pressure amplifier: supplied intel says EPSS 0.00046 and not KEV-listed, with no validated active exploitation evidence.
Why not higher?
It is not higher because this is not a one-packet internet RCE, auth bypass, or wormable edge bug. The exploit path assumes an exposed diagnostics page, a human viewing the HTML page, and enough same-origin value to make the XSS worthwhile.
Why not lower?
It is not lower because many teams do expose FPM status for troubleshooting, and some do it on the same hostname as production apps. If that operational shortcut exists, this bug can absolutely turn into session theft or authenticated action abuse against the victim browser context.
What to do — in priority order.
- Restrict the status page to localhost or monitoring IPs — Apply web-server ACLs or reverse-proxy allowlists in normal change control. For a LOW verdict there is no SLA (treat as backlog hygiene), but this is the single best compensating control because it kills the browser-accessible prerequisite entirely.
- Disable
pm.status_pathwhere it is not operationally required — Remove or comment the directive in unused pools, then reload PHP-FPM during the next routine maintenance cycle. This is the cleanest way to eliminate exposure without waiting on package rollout. - Serve status on a separate internal-only origin — If operations truly need the page, move it behind a distinct hostname or management vhost not sharing cookies with production applications. For LOW, do this as backlog hygiene rather than emergency response.
- Add a restrictive CSP on the status endpoint — Set a web-server header such as
Content-Security-Policy: default-src 'none'; style-src 'self' 'unsafe-inline'if your status view still needs HTML. CSP is not perfect, but it reduces post-injection payoff and should be deployed in the next normal config update.
- Generic server EDR does not stop browser-side JavaScript running in an admin's browser.
- MFA does not meaningfully help once malicious script executes inside an already-authenticated browser session on the same origin.
- A WAF alone is unreliable here because the payload can be encoded in request URIs and the vulnerable reflection is inside a diagnostics page, not a standard application route.
Crowdsourced verification payload.
Run this on the target Linux host that serves PHP-FPM, not from an auditor workstation. Invoke it as sudo bash ./check-cve-2026-6735.sh; it needs read access to PHP-FPM binaries and pool config directories, so root or equivalent read privileges are recommended. The script is upstream-version aware and treats distro-backported packages conservatively as UNKNOWN when versioning is ambiguous.
#!/usr/bin/env bash
# check-cve-2026-6735.sh
# Detect likely exposure to CVE-2026-6735 (PHP-FPM status endpoint XSS)
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
say() { echo "$1"; }
have_cmd() { command -v "$1" >/dev/null 2>&1; }
ver_lt() {
# returns 0 if $1 < $2
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" != "$2" ]
}
find_php_fpm_bin() {
local c
for c in php-fpm php-fpm8.5 php-fpm8.4 php-fpm8.3 php-fpm8.2 php-fpm8.1 php-fpm8.0 php-fpm7.4; do
if have_cmd "$c"; then
echo "$c"
return 0
fi
done
return 1
}
get_php_fpm_version() {
local bin="$1"
"$bin" -v 2>/dev/null | awk '/^PHP / {print $2; exit}'
}
branch_fixed_version() {
case "$1" in
8.2) echo "8.2.31" ;;
8.3) echo "8.3.31" ;;
8.4) echo "8.4.21" ;;
8.5) echo "8.5.6" ;;
*) echo "" ;;
esac
}
status_path_enabled() {
local found=1
local dirs=(
/etc/php-fpm.d
/etc/php/*/fpm/pool.d
/usr/local/etc/php-fpm.d
/usr/local/etc/php-fpm.d/*.conf
/opt/remi/php*/root/etc/php-fpm.d
)
# shellcheck disable=SC2086
grep -R -n -E '^[[:space:]]*pm\.status_path[[:space:]]*=' ${dirs[@]} 2>/dev/null | grep -v '^[[:space:]]*#' >/dev/null 2>&1
found=$?
return $found
}
BIN="$(find_php_fpm_bin || true)"
if [ -z "${BIN:-}" ]; then
say "UNKNOWN: php-fpm binary not found"
exit 2
fi
VER="$(get_php_fpm_version "$BIN")"
if [ -z "${VER:-}" ]; then
say "UNKNOWN: unable to determine PHP-FPM version from $BIN"
exit 2
fi
BRANCH="$(echo "$VER" | awk -F. '{print $1"."$2}')"
FIXED="$(branch_fixed_version "$BRANCH")"
if [ -z "$FIXED" ]; then
say "UNKNOWN: PHP-FPM version $VER is outside upstream affected branches or may rely on distro backports"
exit 2
fi
if ! status_path_enabled; then
if ver_lt "$VER" "$FIXED"; then
say "UNKNOWN: vulnerable upstream version $VER detected, but no enabled pm.status_path found in common config locations"
exit 2
else
say "PATCHED: version $VER is at or above fixed upstream level $FIXED and no enabled status path was found"
exit 0
fi
fi
if ver_lt "$VER" "$FIXED"; then
say "VULNERABLE: php-fpm version $VER is below fixed version $FIXED and pm.status_path appears enabled"
exit 1
fi
say "PATCHED: php-fpm version $VER is at or above fixed version $FIXED; pm.status_path may be enabled, but upstream fix is present"
exit 0
If you remember one thing.
pm.status_path enabled, then strip external access or disable the endpoint where it is not needed. Under the noisgate mitigation SLA there is no SLA for LOW — treat this as backlog hygiene, not an emergency — and under the noisgate remediation SLA it is also backlog hygiene, so fold upgrades to 8.2.31 / 8.3.31 / 8.4.21 / 8.5.6 or distro backports into the next routine web-stack maintenance cycle while immediately fixing any accidentally internet-reachable status pages you discover.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.