Details
-
Bug
-
Status: Closed (View Workflow)
-
Critical
-
Resolution: Fixed
-
10.11, 11.4, 12.3
-
None
-
Can result in unexpected behaviour
-
validation of proxy protocol v1 header is tightened, according to the specification
-
Q4/2026 Server Maintenance, Q4/2026 Server Development
Description
The v1 (text) header parser in `sql/proxy_protocol.cc` accepts lines that the [PROXY protocol spec](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) (section 2.1) says must be rejected:
1. Length. The server reads up to `MAX_PROXY_HEADER_LEN` (256) bytes looking for the line end. The spec says: "If the CRLF sequence is not found in the first 107 characters, the receiver should declare the line invalid."
2. Terminator. The server ends the line at a bare `\n`. The spec says the receiver must not tolerate a single CR or LF to end the line.
3. Padding and trailing data. `parse_v1_header()` uses `sscanf("PROXY %s %s %s %d %d")`. That skips any run of whitespace between fields and ignores anything after the fifth field. The spec requires exactly one space between fields and no extra bytes.
For `UNKNOWN` the spec does say to ignore everything up to the CRLF, but the same 107-byte and CRLF rules apply.
How to repeat: with `--proxy-protocol-networks` covering the client, send this over a raw TCP connection:
`"PROXY TCP4 1.2.3.4 5.6.7.8 1234 5678" + spaces up to 255 bytes + "\n"`
The header is parsed as valid, and the client address becomes 1.2.3.4.
*Side effect:* with name resolution enabled, the server then does a real reverse-DNS lookup of the address from the header. A DBUG trace shows `ip_to_hostname ... Resolving '1.2.3.4'...`. `test_proxy_header_limits()` in `tests/mysql_client_test.c` sends exactly this header, so the test makes a real DNS lookup.
*Suggested fix:*
- Cap v1 lines at 107 bytes.
- Require CRLF.
- Parse strictly: single spaces, nothing trailing except for `UNKNOWN`.