Hi,

HAProxy 2.6.30 was released on 2026/06/26. It added 49 new commits
after version 2.6.29.

HAProxy 2.6 is in "critical fixes only" maintenance mode. So this release is
lighter than the other recent releases. Notably, most QUIC and HTTP/3 fixes
were not backported: the QUIC stack remains experimental in 2.6, the
backport risk is high, and the risk of introducing regressions outweighs the
benefits for the small number of users running QUIC on such an old
branch. Production deployments requiring QUIC support should migrate to a
more recent branch such as 3.2. Only one isolated QUIC mux draining fix was
retained, along with a few QPACK decoder fixes that apply to a shared code
path.

The HTTP/1 parser received a fix to filter out all "h2c" values from Upgrade
headers during parsing, preventing protocol confusion when a client sends
unsupported upgrade requests. The WebSocket protocol token is no longer
masked when multiple protocols appear in the Upgrade header.

A large number of bugs were fixed in the DNS resolver code. A validation bug
was fixed in resolv_read_name() where a name compression pointer was not
validated against the response bounds, potentially causing out-of-bounds
memory reads when processing crafted DNS responses. A bug in
resolv_dn_label_to_str() were fixed: the label size check used an incorrect
comparison. A related fix prevents garbage data from being appended past the
domain name. A memory leak of a sockaddr structure was fixed in the
dns_session_init() error path. Minor error-path fixes addressed a dangling
pointer on dns_dgram_init() failure, and the do-resolve() action parser now
properly reports expression errors.

In the FCGI multiplexer, an integer overflow was fixed: the unsigned 16-bit
integer used for the record length overflowed to 0 when the record length
was 65535 and padding was non-zero, causing the state machine to skip
consuming buffer data and parse the remaining bytes as a new FCGI record
header. This could only happen for unknown records or for STDOUT records
received after the end of the response. CVE-2026-55203 was assigned to this
overflow. It must be noted however that the assigned severity is excessively
high relative to the actual exploitability: triggering this bug requires the
FCGI backend server itself to be compromised and to craft a malicious
response with exactly those values, which is well outside a normal threat
model where the backend is trusted. Additionally, stream ID 0 was not
rejected for application records as required by the FCGI specification,
potentially causing incorrect demultiplexing. When trying to forward data to
a server whose stream was already closed, the FCGI mux claimed to have
consumed buffered data without actually draining them, causing the upper
layer to loop endlessly trying to send. A minor fix also corrected the
computation of contiguous data in the demux buffer.

Several bugs were fixed in the H1 and H2 multiplexers. In the H1 mux, the
connection/upgrade header value is now duplicated before being parsed when
building outgoing request headers, as the parsing modified the value
in-place and could corrupt shared data. The 'h1-case-adjust-file' directive
was not resolving a relative file path to an absolute path at parse time,
causing failures when multiple configuration files were loaded. A possible
failure from strdup() was also left unhandled. In the H2 mux, when
forwarding data to a server whose stream was already closed, the mux claimed
to have consumed buffered data without actually draining them; this could
cause the upper layer to keep retrying in a loop and potentially trigger the
watchdog. The HEADERS frame length is now also validated before reading the
stream dependency field.

One fix was applied to the QUIC multiplexer: an issue in
qcs_http_reset_buf() caused the entire buffer to be reset unconditionally
instead of draining only the requested amount, which could silently discard
unsent data when a stream filter was registered on the data forwarding
stage.

Several bugs were fixed in the QPACK decoder, which is shared between QUIC
and other code paths. Index calculation in debug functions was incorrect. A
potential null-pointer dereference was fixed in qpack_dht_insert() when the
memory pool was exhausted. A sign bit mask was wrong in
qpack_decode_fs_pfx(), potentially causing incorrect header value
decoding. Error handling in huff_dec() called from qpack_decode_fs() was not
properly propagating the error.

Two bugs were fixed in the Lua integration. An integer underflow was
possible in the Lua cosocket line-read path, causing memory corruption when
fewer bytes than expected were received. Lua was also not filtering CR, LF,
and NUL characters from HTTP headers set by scripts, which could allow
header injection attacks.

Two bugs were fixed in the cache subsystem. The primary hash was not always
verified in get_secondary_entry(), which could lead to incorrect cache hits
returning the wrong cached response. The maxage value was being overwritten
instead of properly copied during parsing of cache-control directives.

Two locking bugs were fixed in the dictionary subsystem, which is used
internally for string deduplication. The read lock was not held while
incrementing the refcount in dict_insert(), creating a race condition where
two concurrent inserts could corrupt the refcount of a shared entry. The
write lock was not held while decrementing the refcount in
dict_entry_unref(), allowing a concurrent lookup to observe an inconsistent
state and potentially access freed memory. A further race on insert
collision was fixed where the refcount was not properly updated when two
threads inserted the same key simultaneously.

Several SSL/TLS fixes are included. With TLS 1.3 0-RTT, the early data
buffer was freed when emptied but more early data could still arrive; the
buffer is now reset rather than freed until all early data has been
received, preventing use-after-free. SNI character validation was added to
the dynamic certificate generation code to prevent SAN certificate injection
through crafted SNI values. The null-terminated servername is now properly
used in the SSL hello parser. A memory leak in the ECDSA signature
conversion error path was also fixed.

When L7 retries were configured and the maximum retry count was reached on a
reused connection, the stream was silently closed on the client side instead
of properly returning a 502 or 425 error, leaving the client without a
meaningful response. The HTTP authentication token checker was not verifying
against the whole token, allowing partial matches to succeed. The HTTP
client CLI now properly destroys its context if it fails to start.

Two health check bugs were fixed. External checks were not being excluded
from the tcpcheck post-config phase, which could cause a NULL pointer
dereference at startup. Additionally, when a server inherited ALPN settings
from a default server, the health check was using a reference to the default
server's ALPN string rather than a proper copy, which could lead to
incorrect ALPN negotiation or unexpected behavior if the default server
configuration was modified.

A NULL pointer dereference was fixed in the HPACK table code: when the
memory pool was exhausted, hpack_dht_defrag() could return NULL and be
immediately dereferenced, crashing the worker process. CVE-2026-55204 was
assigned to this issue. Here again the assigned severity is excessively
high: the condition only arises when the process is already out of memory,
at which point the allocator failure itself is likely to cause other
problems before this specific code path is even reached. The probability of
hitting this particular NULL dereference in a production environment is
extremely thin.

A NULL pointer dereference was fixed in the authentication code when an
unconfigured password entry (NULL) was accessed during authentication, which
could crash the process when a user with no password was configured. The
log-forward module treated the month field as a signed integer, which could
cause incorrect log timestamps when the high bit was set.

Finally, a few other minor issues were addressed: the be2hex sample
converter chunk size was not bounded, potentially causing oversized output;
the client hello parser had incorrect bounds checks for the handshake
length; the addons/51d module was not NUL-terminating headers before passing
them to the Trie API; parameter value validation in get_server_ph_post() had
an incorrect comparison; and consistent hash balancing for newly added
servers was broken.

Thanks to everyone for your help on this release!

Please find the usual URLs below :
   Site index       : https://www.haproxy.org/
   Documentation    : https://docs.haproxy.org/
   Wiki             : https://github.com/haproxy/wiki/wiki
   Discourse        : https://discourse.haproxy.org/
   Slack channel    : https://slack.haproxy.org/
   Issue tracker    : https://github.com/haproxy/haproxy/issues
   Sources          : https://www.haproxy.org/download/2.6/src/
   Git repository   : https://git.haproxy.org/git/haproxy-2.6.git/
   Git Web browsing : https://git.haproxy.org/?p=haproxy-2.6.git
   Changelog        : https://www.haproxy.org/download/2.6/src/CHANGELOG
   Dataplane API    : 
https://github.com/haproxytech/dataplaneapi/releases/latest
   Pending bugs     : https://www.haproxy.org/l/pending-bugs
   Reviewed bugs    : https://www.haproxy.org/l/reviewed-bugs
   Code reports     : https://www.haproxy.org/l/code-reports
   Latest builds    : https://www.haproxy.org/l/dev-packages


---
Complete changelog :
Amaury Denoyelle (1):
      BUG/MINOR: server: fix add server with consistent hash balancing

Christopher Faulet (18):
      BUG/MINOR: httpclient-cli: Destroy http-client context if failing to 
start it
      BUG/MEDIUM: h1: Skip all h2c values from Upgrade headers during parsing
      BUG/MINOR: h1: Don't mask websocket protocol if multiple protocols used
      BUG/MEDIUM: server: Duplicate healthcheck's alpn inherited from default 
server
      BUG/MEDIUM: resolvers: Fix test on dn label size in 
resolv_dn_label_to_str()
      BUG/MEDIUM: dict: hold lock while decrementing refcount in 
dict_entry_unref
      BUG/MEDIUM: hlua: Fix integer underflow when receiving line from lua 
cosocket
      BUG/MEDIUM: mux-fcgi: reject stream ID 0 for application records
      BUG/MINOR: mux-fcgi: Use relative offset to compute contig data in demux 
buf
      Revert "BUG/MEDIUM: dns: fix long loops in additional records parse on name 
failure"
      BUG/MINOR: cache: Fix copy of value when parsing maxage
      BUG/MEDIUM: mux-h1: Dup connection/upgrade value to parse it when making 
headers
      BUG/MEDIUM: check: Skip tcpcheck post-config for external checks
      BUG/MEDIUM: http-ana: Don't ignore L7 retry errors
      BUG/MINOR: mux-h1: Properly resolve file path for 'h1-case-adjust-file'
      BUG/MEDIUM: mux-fcgi: Truly drain outgoing HTX data when the stream is 
closed
      BUG/MEDIUM: mux-h2: Truly drain outgoing HTX data when the stream is 
closed
      BUG/MEDIUM: mux-quic: Drain the given amount of data in 
qcs_http_reset_buf()

Frederic Lecaille (4):
      BUG/MINOR: qpack: Fix index calculation in debug functions
      BUG/MINOR: qpack: fix potential null-pointer dereference in 
qpack_dht_insert()
      BUG/MINOR: qpack: fix sign bit mask in qpack_decode_fs_pfx()
      BUG/MINOR: qpack: fix huff_dec() error handling in qpack_decode_fs()

Ilia Shipitsin (1):
      BUG/MINOR: mux_h1: handle a possible strdup() failure

Olivier Houchard (1):
      BUG/MEDIUM: ssl: Don't free the early data buffer too early

Tristan Madani (2):
      BUG/MINOR: hpack-tbl: add missing NULL check after hpack_dht_defrag()
      BUG/MEDIUM: mux-fcgi: fix uint16_t overflow in drl += drp

William Lallemand (2):
      BUG/MEDIUM: auth: fix unconfigured password NULL deref
      BUG/MINOR: ssl-gencert: validate SNI characters to prevent SAN 
certificate injection

Willy Tarreau (20):
      BUG/MEDIUM: dict: hold read lock while incrementing refcount in 
dict_insert
      BUG/MINOR: backend: correct parameter value validation in 
get_server_ph_post()
      BUG/MEDIUM: dns: fix long loops in additional records parse on name 
failure
      BUG/MEDIUM: resolvers: fix name compression pointer validation in 
resolv_read_name()
      BUG/MEDIUM: dns: fix memory leak of sockaddr in dns_session_init() error 
path
      BUG/MINOR: dns: fix dangling dgram pointer on dns_dgram_init() failure 
path
      BUG/MINOR: resolvers: report the expression error in the do-resolve() 
action parser
      BUG/MINOR: jwt: fix possible memory leak in convert_ecdsa_sig() error path
      BUG/MEDIUM: log-forward: make sure the month is unsigned
      BUG/MINOR: resolvers: fix room for trailing zero in 
resolv_dn_label_to_str()
      BUG/MINOR: resolvers: fix risk of appending garbage past the domain name
      BUG/MINOR: mux-h2: validate HEADERS frame length before reading stream dep
      BUG/MINOR: dict: fix refcount race on insert collision
      BUG/MINOR: sample: limit the be2hex converter's chunk size
      BUG/MEDIUM: cache: always verify the primary hash in get_secondary_entry()
      BUG/MINOR: http-fetch: check against the whole token in get_http_auth()
      BUG/MINOR: payload: fix the handshake length bounds check 
smp_client_hello_parse()
      BUG/MINOR: ssl-hello: make use of the null-terminated servername
      BUG/MINOR: addons/51d: NUL-terminate headers before passing them to Trie 
API
      BUG/MINOR: hlua: prevent Lua from passing CR/LF/NUL in HTTP headers

--
Christopher Faulet



Reply via email to