From 99a5ad7441de9914246c7863adb6997396008b9d Mon Sep 17 00:00:00 2001
From: Jakub Zelenka <bukka@php.net>
Date: Sun, 3 May 2026 20:01:41 +0200
Subject: [PATCH] GHSA-7qg2-v9fj-4mwv: [fpm] XSS within status endpoint

Fixes GHSA-7qg2-v9fj-4mwv
Fixes CVE-2026-6735
---
 sapi/fpm/fpm/fpm_status.c                     | 34 +++++++++++--
 .../tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt | 48 +++++++++++++++++++
 2 files changed, 78 insertions(+), 4 deletions(-)
 create mode 100644 sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt

Index: php-7.4.33/sapi/fpm/fpm/fpm_status.c
===================================================================
--- php-7.4.33.orig/sapi/fpm/fpm/fpm_status.c
+++ php-7.4.33/sapi/fpm/fpm/fpm_status.c
@@ -483,8 +483,8 @@ int fpm_status_handle_request(void) /* {
 		if (full_syntax) {
 			unsigned int i;
 			int first;
-			zend_string *tmp_query_string;
-			char *query_string;
+			zend_string *tmp_query_string, *tmp_request_uri_string;
+			char *query_string, *request_uri_string;
 			struct timeval duration, now;
 #ifdef HAVE_FPM_LQ
 			float cpu;
@@ -511,13 +511,27 @@ int fpm_status_handle_request(void) /* {
 					}
 				}
 
+				request_uri_string = NULL;
+				tmp_request_uri_string = NULL;
+				if (proc.request_uri[0] != '\0') {
+					if (encode) {
+						tmp_request_uri_string = php_escape_html_entities_ex(
+								(const unsigned char *) proc.request_uri,
+								strlen(proc.request_uri), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT,
+								NULL, /* double_encode */ 1);
+						request_uri_string = ZSTR_VAL(tmp_request_uri_string);
+					} else {
+						request_uri_string = proc.request_uri;
+					}
+				}
+
 				query_string = NULL;
 				tmp_query_string = NULL;
 				if (proc.query_string[0] != '\0') {
 					if (!encode) {
 						query_string = proc.query_string;
 					} else {
-						tmp_query_string = php_escape_html_entities_ex((unsigned char *)proc.query_string, strlen(proc.query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, 1);
+						tmp_query_string = php_escape_html_entities_ex((unsigned char *)proc.query_string, strlen(proc.query_string), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT, NULL, 1);
 						query_string = ZSTR_VAL(tmp_query_string);
 					}
 				}
@@ -545,7 +559,7 @@ int fpm_status_handle_request(void) /* {
 					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,
@@ -558,6 +572,9 @@ int fpm_status_handle_request(void) /* {
 				PUTS(buffer);
 				efree(buffer);
 
+				if (tmp_request_uri_string) {
+					zend_string_free(tmp_request_uri_string);
+				}
 				if (tmp_query_string) {
 					zend_string_free(tmp_query_string);
 				}
