From: Olivier Houchard Date: Thu, 6 Aug 2026 11:54:52 +0000 (+0200) Subject: BUG/MINOR: mux-fcgi: sanitize the STDERR records before logging them X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f495d486e60941548eb13b1e9700be868617471f;p=thirdparty%2Fhaproxy.git BUG/MINOR: mux-fcgi: sanitize the STDERR records before logging them fcgi_strm_handle_stderr() emits one log line per STDERR record, appending its own newline, but passes the record payload to app_log() with a bare "%s", and neither app_log() nor __send_log() escape anything. FastCGI applications routinely echo parts of the request in their warnings, so a client whose input is reflected there can insert CR/LF and turn one record into several log lines, or insert ESC sequences which the operator's terminal interprets when reading the log. Verified with an application writing "bad input 'x\r\nFAKE-INJECTED-LINE: ...\033[31m...'": the syslog datagram carries all of it verbatim. Escaping data emitted to logs is normally a configuration matter, but this path bypasses the log-format machinery entirely, and the intent here is clearly one record per line. Let's replace the control characters with a dot before logging, which is a single pass over a record that is only ever produced when the application writes to its stderr. Only controls are replaced, so that the UTF-8 messages commonly found in such warnings are left intact. This has been there since the FCGI mux was introduced in 2.1 by commit 99eff65f4 ("MEDIUM: mux-fcgi: Add the FCGI multiplexer"). It may be backported to all stable versions. Reported-by: Claude (ANT-2026-9JD79F3M) --- diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c index 16ccdfe42..94995bca3 100644 --- a/src/mux_fcgi.c +++ b/src/mux_fcgi.c @@ -2456,7 +2456,7 @@ static int fcgi_strm_handle_stderr(struct fcgi_conn *fconn, struct fcgi_strm *fs { struct buffer *dbuf; struct buffer tag; - size_t ret; + size_t ret, i; TRACE_ENTER(FCGI_EV_RX_RECORD|FCGI_EV_RX_STDERR, fconn->conn, fstrm); dbuf = &fconn->dbuf; @@ -2477,6 +2477,11 @@ static int fcgi_strm_handle_stderr(struct fcgi_conn *fconn, struct fcgi_strm *fs fconn->drl -= ret; TRACE_PROTO("FCGI STDERR record rcvd", FCGI_EV_RX_RECORD|FCGI_EV_RX_STDERR, fconn->conn, fstrm, 0, (size_t[]){ret}); + for (i = 0; i < ret; i++) { + if (iscntrl((unsigned char)trash.area[i])) + trash.area[i] = '.'; + } + trash.area[ret] = '\n'; trash.area[ret+1] = '\0'; tag.area = fconn->app->name; tag.data = strlen(fconn->app->name);