Hi,
HAProxy 2.8.16 was released on 2025/10/03. It added 111 new commits
after version 2.8.15.
As promised in the 2.8.16 announce, here is the usual description of bugs
fixed by this release.:
* The most important one is obviously the mjson JSON decoder issue
described in the previous mail. Decoding of numbers with large exponents
was eating a lot of CPU and could even trigger the watchdog and kill the
process. "json_query()", "jwt_header_query()", and "jwt_payload_query()"
converters was affected. This bug was assigned CVE-2025-11230 and
affected all versions featuring the JSON decoder, or 2.4 and above.
* In the QUIC part, QUIC address format on a server line is inappropriate
and should be rejected (and now is). And wrong error codes were used to
missing or invalid transport parameters. Some others were not rejected.
* H2 on backend side could mishandle a connection error before the preface
and cause a wakeup loop while data from other streams were waiting to be
evacuated to the client. It caused a loop and a crash reported for the
first time in issue #3020 though it's been there since backend H2 is
supported.
* In both H2 and H3, the 'Z' character (in upper case) was not rejected as
expected from header field names. Thanks to @zhanhb, it now fixed.
* We've also addressed the detection of forbidden chars in the Host
header in H1, H2 and H3.
* On H2, streams are now reset with NO_ERROR and not CANCEL when the
server responds before the end of the request and closes, making it
clear to the client that the response is valid and not an error.
* On H3, multiple Host headers were still preserved, only the values were
compared. We are now aligned with the H1 and H2 by dropping extraneous
headers. Information about :scheme pseudo-header were not properly
reported at the HTX level, preventing the H2 multiplexer to preserve it
on server side.
* It was possible to not respect healthchecks timeout when the "check"
timeout was defined with a high "connect" timeout. In that case, the
check task was not woken up as expected on timeout expiration.
* An old issue about the FD insertion in the fdtab array was revealed by
the recent changes to support different CPU alloocation policies. The
wrong thread group was used and depending on the mapping, this could
lead to a crash.
* There was an issue when loading CA certificates from a directory. Only
the first certificate of each file was loaded. It was an issue on some
systems (debian/ubuntu ones were not affected). The issue was fixed by
using X509_STORE_load_locations() on each file instead of loading
certificates by hand.
* The %ID log alias was not suitable for use in unique-id-format
construction, where it would cause an infinite recursive loop during
evaluation. Now it will detect the situation and evaluate to empty in
this case. In addition, the evaluation of the ID is now made closer to
where it's evaluated so as to avoid inconsistencies (e.g.
unique-id-format referencing elements not available at log production
time).
* L6/L7 sample fetch functions cannot be used in Lua services since they
don't have access to the channel, yet L6 was not rejected, possibly
wasting time when users would try to implement them and figure why they
don't work.
* In the SSL stack, a regression in certificate selection was fixed which
could cause issue if haproxy was configured with TLS 1.2 as maximum
version supported. Early-data support on the backend side was adjusted
as it was broken for some time now, as no data could be emitted prior to
the handshake completion.
* The httpclient was progressively refined as its usage is becoming more
prevalent. Most notably, it is able to deal better with large transfers.
It can also now properly handle interim and early HTTP responses.
* On the LUA side, read and write events are properly notify when using
the socket class to avoid infinite wait when the write side has been
blocked earlier.
* For resolvers, an unexpected CPU usage could be experienced because
there was no delay on connection retries. It was observed with a
nameserver with invalid network settings. There is now a one-second delay
between two connections. Related to this issue, it was also possible to
have an accumulation of DNS sessions. The number of DNS sessions is now
tracked When we reach a threshold (set to 100), we consider that the link
to the dns server is broken (at least temporarily) and we stop creating
new sessions until one of the existing one eventually succeeds.
* The error reported by the master process when a worker crashes during
its configuration parsing was improved to include the PID of the worker
and the exist status code. In addition, because of an issue with the
sockpair protocol on macOS
(https://man.freebsd.org/cgi/man.cgi?sendmsg(2)), the startup/reload was
no longer working and this since the master-worker rework. This was
fixed by using a blocking read in the master to receive the
acknowledgment from the worker before closing the recv fd on the sending
side. However, the same issue exists on the master CLI. Unfortunately no
solution was found on macOS.
* A crash could be experienced if a certificate or a CA was updated on the
CLI while an OCSP response was being updated by corrupting the update
tree. This tree is now protected by a lock.
* The normalization of FQDNs from resolvers response was not properly
performed. It was fixed by converting them to lower case.
* The ALPN used to perform healthchecks over SSL is now properly inherited
from server settings when no "check-alpn" directive is used. This could
lead to healthchecks failure for servers relying explicitly on H2. And a
Use-After-Free was possible if a "check-alpn" parameter inherited from
the default server was overridden on the server line because the default
value was released, preventing any reuse by another server.
* Since we made it possible for a bind_conf to listen to multiple thread
groups with shards in 2.8, the per-listener connection count was not
properly transferred to the target listener with the connection when
switching to another thread group. This resulted in one listener
possibly reaching high values and another one possibly reaching negative
values. Usually it was not visible, unless a maxconn was set on the
bind_conf, in which case comparisons would quickly put an end to the
willingness to accept new connections. This problem only happened when
thread groups were enabled.
* In lua; Channel:data() and Channel:line() functions was fixed to respect
the documentation.
* On the CLI, no error was reported when too many arguments were passed for
a command. Instead, arguments above the limit (64 by default) were just
silently ignored.
* Haproxy could stop too early on soft stop, without processing incoming
traffic, which was visible with broken connections during reloads. To
fix the issue, threads now ignore the the stopping condition until the
signal queue is empty.
Some improvements where also backported:
* "send-proxy" and "send-proxy-v2" options are not relevant nor supported
on a ring server. It is now explicitly ignored and a warning is emitted.
* The API for the lua HTTPMessage "class" was improved to be able to change
the body length. It was mandatory to be able to write a lua filter
altering the message payload. HTTPMessage:set_body_len() can now be used
for this purpose.
* Still in lua, The HTTP client is not supposed to be used to process
several requests but there was nothing to prevent this usage. An error is
now triggered in that case and the lua documentation was updated to be
clear on this point.
* The CI now relies on vtest2 which finally contains the fixes we were
relying on and which is going to evolve.
Thanks everyone for your help !
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
Q&A from devs : https://github.com/orgs/haproxy/discussions
Sources : https://www.haproxy.org/download/2.8/src/
Git repository : https://git.haproxy.org/git/haproxy-2.8.git/
Git Web browsing : https://git.haproxy.org/?p=haproxy-2.8.git
Changelog : https://www.haproxy.org/download/2.8/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 (17):
MINOR: quic: extend return value during TP parsing
BUG/MINOR: quic: use proper error code on missing CID in TPs
BUG/MINOR: quic: use proper error code on invalid server TP
BUG/MINOR: quic: reject retry_source_cid TP on server side
BUG/MINOR: quic: use proper error code on invalid received TP value
BUG/MINOR: quic: fix TP reject on invalid max-ack-delay
BUG/MINOR: quic: reject invalid max_udp_payload size
BUG/MINOR: mux-quic: do not decode if conn in error
BUG/MINOR: config/server: reject QUIC addresses
DOC: list missing global QUIC settings
BUG/MINOR: mux-h1: fix wrong lock label
BUG/MINOR: quic: do not emit probe data if CONNECTION_CLOSE requested
MINOR: doc: add missing statistics column
MINOR: doc: add missing statistics column
BUG/MINOR: quic: fix room check if padding requested
OPTIM: check: do not delay MUX for ALPN if SSL not active
BUG/MEDIUM: checks: fix ALPN inheritance from server
Aurelien DARRAGON (10):
MINOR: applet: add appctx_schedule() macro
BUG/MINOR: dns: add tempo between 2 connection attempts for dns servers
CLEANUP: dns: remove unused dns_stream_server struct member
BUG/MINOR: dns: prevent ds accumulation within dss
BUG/MINOR: proxy: only use proxy_inc_fe_cum_sess_ver_ctr() with frontends
BUG/MINOR: cli: fix too many args detection for commands
BUG/MINOR: threads: fix soft-stop without multithreading support
BUG/MINOR: sink: detect and warn when using "send-proxy" options with
ring servers
DOC: config: restore default values for resolvers hold directive
BUG/MINOR: hlua: take default-path into account with lua-load-per-thread
Christopher Faulet (36):
BUG/MINOR: cli: Issue an error when too many args are passed for a command
BUG/MINOR: mux-h1: Don't pretend connection was released for TCP>H1>H2
upgrade
BUG/MINOR: mux-h1: Fix trace message in h1_detroy() to not relay on
connection
BUG/MINOR: hlua: Fix Channel:data() and Channel:line() to respect
documentation
MEDIUM: hlua: Add function to change the body length of an HTTP Message
BUG/MINOR: mux-h2: Reset streams with NO_ERROR code if full response was
already sent
BUG/MINOR: h3: Set HTX flags corresponding to the scheme found in the
request
REGTESTS: Make the script testing conditional set-var compatible with
Vtest2
CI: vtest: Rely on VTest2 to run regression tests
REGTESTS: Explicitly allow failing shell commands in some scripts
BUG/MEDIUM: httpclient: Throw an error if an lua httpclient instance is
reused
DOC: hlua: Add a note to warn user about httpclient object reuse
BUG/MEDIUM: check: Requeue healthchecks on I/O events to handle check
timeout
BUG/MEDIUM: check: Set SOCKERR by default when a connection error is
reported
BUG/MINOR: stream: Avoid recursive evaluation for unique-id based on
itself
BUG/MINOR: log: Be able to use %ID alias at anytime of the stream's
evaluation
BUG/MEDIUM: hlua: Forbid any L6/L7 sample fetche functions from lua
services
BUG/MEDIUM: mux-h2: Properly handle connection error during preface
sending
BUG/MINOR: hlua: Skip headers when a receive is performed on an HTTP
applet
BUG/MEDIUM: hlua: Report to SC when data were consumed on a lua socket
BUG/MEDIUM: hlua: Report to SC when output data are blocked on a lua
socket
BUG/MEDIUM: dns: Reset reconnect tempo when connection is finally
established
BUG/MEDIUM: http-client: Don't wake http-client applet if nothing was
xferred
BUG/MEDIUM: http-client: Properly inc input data when HTX blocks are
xferred
BUG/MEDIUM: http-client: Ask for more room when request data cannot be
xferred
BUG/MINOR: http-client: Ignore 1XX interim responses in non-HTX mode
BUG/MINOR: http-client: Reject any 101-switching-protocols response
BUG/MEDIUM: http-client: Drain the request if an early response is
received
BUG/MEDIUM: http-client: Notify applet has more data to deliver until the
EOM
BUG/MINOR: applet: Don't trigger BUG_ON if the tid is not on appctx init
BUG/MEDIUM: http-client: Test HTX_FL_EOM flag before commiting the HTX
buffer
BUG/MEDIUM: server: Duplicate healthcheck's alpn inherited from default
server
BUG/MINOR: server: Update healthcheck when server settings are changed
via CLI
BUG/MINOR: h3: Fix errors introduced because of failed backport
Revert "BUG/MINOR: config/server: reject QUIC addresses"
Revert "BUILD: makefile: enable backtrace by default on musl"
Frederic Lecaille (3):
CLEANUP: quic: Useless BIO_METHOD initialization
MINOR: quic: Add useful error traces about qc_ssl_sess_init() failures
BUG/MINOR: quic: wrong QUIC_FT_CONNECTION_CLOSE(0x1c) frame encoding
Lukas Tribus (3):
DOC: ring: refer to newer RFC5424
DOC: management: fix typo in commit f4f93c56
DOC: config: recommend single quoting passwords
Olivier Houchard (6):
BUG/MEDIUM: fd: Use the provided tgid in fd_insert() to get tgroup_info
BUG/MEDIUM: threads: Disable the workaround to load libgcc_s on macOS
BUG/MEDIUM: ssl: Fix 0rtt to the server
BUG/MEDIUM: ssl: fix build with AWS-LC
BUG/MEDIUM: h1: Allow reception if we have early data
BUG/MEDIUM: ssl: create the mux immediately on early data
Remi Tricot-Le Breton (4):
BUG/MINOR: jwt: Copy input and parameters in dedicated buffers in
jwt_verify converter
DOC: Fix 'jwt_verify' converter doc
BUG/MINOR: init: Initialize random seed earlier in the init process
BUG/MINOR: ocsp: Crash when updating CA during ocsp updates
Valentine Krasnobaeva (8):
BUG/MINOR: limits: compute_ideal_maxconn: don't cap remain if
fd_hard_limit=0
BUG/MINOR: init: relax LSTCHK_NETADM checks for non root
MINOR: compiler: add __nonstring macro
DOC: config: prefer-last-server: add notes for non-deterministic
algorithms
BUG/MINOR: halog: exit with error when some output filters are set
simultaneosly
BUG/MINOR: stick-table: cap sticky counter idx with tune.nb_stk_ctr
instead of MAX_SESS_STKCTR
BUG/MINOR: acl: set arg_list->kw to aclkw->kw string literal if aclkw is
found
BUG/MINOR: resolvers: always normalize FQDN from response
William Lallemand (6):
BUG/MEDIUM: ssl/clienthello: ECDSA with ssl-max-ver TLSv1.2 and no ECDSA
ciphers
DOC: configuration: add details on prefer-client-ciphers
DOC: management: clarify usage of -V with -c
DOC: unreliable sockpair@ on macOS
DOC: configuration: confuse "strict-mode" with "zero-warning"
BUG/MEDIUM: ssl: ca-file directory mode must read every certificates of a
file
Willy Tarreau (16):
BUG/MAJOR: listeners: transfer connection accounting when switching
listeners
DOC: config: recommend disabling libc-based resolution with resolvers
BUG/MINOR: h3: don't insert more than one Host header
BUILD: makefile: enable backtrace by default on musl
DOC: hlua: fix a few typos in HTTPMessage.set_body_len() documentation
MINOR: http: add a function to validate characters of :authority
BUG/MEDIUM: h2/h3: reject some forbidden chars in :authority before
reassembly
BUG/MEDIUM: h1/h2/h3: reject forbidden chars in the Host header field
SCRIPTS: drop the HTML generation from announce-release
BUG/MINOR: listener: really assign distinct IDs to shards
BUILD: compat: always set _POSIX_VERSION to ease comparisons
BUG/MINOR: haproxy: be sure not to quit too early on soft stop
BUILD: acl: silence a possible null deref warning in parse_acl_expr()
BUG/MINOR: activity: fix reporting of task latency
DOC: config: clarify some known limitations of the json_query() converter
BUG/CRITICAL: mjson: fix possible DoS when parsing numbers
zhanhb (2):
BUG/MINOR: h2: forbid 'Z' as well in header field names checks
BUG/MINOR: h3: forbid 'Z' as well in header field names checks
--
Christopher Faulet