From 3322601b31ccedeb13a3203bbe5fd7b6cb4679a9 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 19 May 2026 09:47:08 +0200 Subject: [PATCH 5/5] GHSA-7qg2-v9fj-4mwv: [fpm] XSS within status endpoint Fixes GHSA-7qg2-v9fj-4mwv Fixes CVE-2026-6735 (cherry picked from commit 99a5ad7441de9914246c7863adb6997396008b9d) (cherry picked from commit 943de7efee24c0e7d826a3469d3b35b4ad0f4193) --- NEWS | 4 ++ sapi/fpm/fpm/fpm_status.c | 20 ++++-- .../tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt | 62 +++++++++++++++++++ 3 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt diff --git a/NEWS b/NEWS index b46e2b0c5d..d8ae595068 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,10 @@ PHP NEWS Backported from 8.2.31 +- FPM: + . Fixed GHSA-7qg2-v9fj-4mwv (XSS within status endpoint). (CVE-2026-6735) + (Jakub Zelenka) + - SOAP: . Fixed GHSA-m33r-qmcv-p97q (Use-after-free after header parsing failure with SOAP_PERSISTENCE_SESSION). (CVE-2026-7261) (ilutov) diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index a2ee398d29..d9a8263089 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -384,8 +384,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ /* no need to test the var 'full' */ if (full_syntax) { int i, first; - size_t len; - char *query_string; + size_t len, len_uri; + char *query_string, *request_uri_string; struct timeval duration, now; #ifdef HAVE_FPM_LQ float cpu; @@ -412,13 +412,22 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ } } + request_uri_string = NULL; + len_uri = 0; + if (proc.request_uri[0] != '\0') { + if (!encode) { + request_uri_string = proc.request_uri; + } else { + request_uri_string = php_escape_html_entities_ex((unsigned char *)proc.request_uri, strlen(proc.request_uri), &len_uri, 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT, NULL, 1 TSRMLS_CC); + } + } query_string = NULL; len = 0; if (proc.query_string[0] != '\0') { if (!encode) { query_string = proc.query_string; } else { - query_string = php_escape_html_entities_ex((unsigned char *)proc.query_string, strlen(proc.query_string), &len, 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, 1 TSRMLS_CC); + query_string = php_escape_html_entities_ex((unsigned char *)proc.query_string, strlen(proc.query_string), &len, 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT, NULL, 1 TSRMLS_CC); } } @@ -445,7 +454,7 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ proc.requests, duration.tv_sec * 1000000UL + duration.tv_usec, proc.request_method[0] != '\0' ? proc.request_method : "-", - proc.request_uri[0] != '\0' ? proc.request_uri : "-", + request_uri_string ? request_uri_string: "-", query_string ? "?" : "", query_string ? query_string : "", proc.content_length, @@ -461,6 +470,9 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ if (len > 0 && query_string) { efree(query_string); } + if (len_uri > 0 && request_uri_string) { + efree(request_uri_string); + } } if (full_post) { diff --git a/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt b/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt new file mode 100644 index 0000000000..55827b1bc8 --- /dev/null +++ b/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt @@ -0,0 +1,62 @@ +--TEST-- +FPM: Test status page +--SKIPIF-- + +--FILE-- +alert(1)', ''); + + $html = run_request('127.0.0.1', $port, '/status', 'full&html'); + var_dump(strpos($html, 'text/html') && strpos($html, 'DOCTYPE') && strpos($html, 'PHP-FPM Status Page')); + var_dump(strpos($html, 'alert(1)') && strpos($html, 'alert(2)')); + var_dump(strpos($html, '