Hi,

HAProxy 3.3.7 was released on 2026/04/23. It added 118 new commits
after version 3.3.6.

This version brings a significant number of bug fixes, more than usual
in part thanks to reports from multiple AI-assisted scans that found
bugs in diverse places. A few of these bugs were ranked as major since
they may have stability or even security impacts depending on configs
and deployments:

  - a severe issue was found in the compression library (slz) where
    specially crafted patterns with tune.bufsize above 17408 or
    tune.maxrewrite below 964 (both non-default) could cause output
    buffer overflows due to the overhead exceeding the promised
    worst-case growth bound of 5 bytes and reach up to 1/16 of the
    input contents. Given that the compression output is hardly
    controllable, and the canaries at the end of the pools will catch
    this at release time, the risk of exploitation by a hostile server
    is close to zero, however it will cause repeated crashes if such a
    crafted file is present on a server and regularly downloaded. A
    workaround consists in keeping tune.maxrewrite at least 1/16 of
    tune.bufsize or just not changing them since the defaults are safe.
    A CVE was requested two weeks ago for this one, I'll mention it when
    it arrives.

  - HTTP/2 incomplete transfer detection was missing for HEADERS frames
    carrying END_STREAM. When relayed to an HTTP/1.1 server that
    responds before the end of the transfer, this can result in bytes
    of the next request over the same connection to be ignored. Most of
    the time it will cause the connection to be dropped due to an
    unparsable request, but when combined with "http-reuse never", or
    on totally idle servers, the client could expect the second request
    to reuse the same connection and perform a content smuggling attack
    that would allow to pass an unverified request to a server. For
    those who can't upgrade, a temporary workaround is to disable
    HTTP/2 by specifying "alpn http/1.1" on bind lines and adding
    "disable-h2-upgrade" in HTTP frontends. A CVE will be requested for
    this one.

  - HTTP/1.1 bodyless messages announcing a non-null Content-Length did
    not force close mode on the backend, potentially causing
    desynchronisation between HAProxy and the server in conjunction
    with other bugs.

  - FCGI record length truncation with large bufsize (>=65544) could
    enable request smuggling into PHP-FPM since the 16-bit
    content_length field silently truncated to 65535 bytes.

  - an unvalidated SNI name_len field in ClientHello could cause OOB
    heap reads of up to 65KB via XXH3, smp_dup(), and log-format leaks
    on any TCP frontend using req.ssl_sni, possibly causing crashes when
    used.

  - ECDSA JWT signatures with ES256/384/512 could cause a heap overflow
    of ~14 bytes in the DER conversion before verification.

  - a number of CLI commands were mistakenly missing the "admin" level
    check, allowing a non-privileged CLI to run them. This includes
    "acme", "add/set/del/show ssl ech", "tls-keys show/set", "ocsp
    set/update/show", "get/add/del/clear/commit/set map/acl". These
    commands now cause a deprecation warning to be emitted in logs for
    versions before 3.3, and are rejected in 3.3 and above. The fix
    consists in appending "level admin" at the end of the "stats socket"
    line in the configuration.

  - the scheduler was found to suffer from a flaw affecting certain
    tasks and tasklets which can mutually wake each other up multiple
    times in the same loop iteration, confiscating CPU bandwidth from
    other tasks and abnormally increasing latencies. A loop counter is
    now tracked per task and the queue processing stops when a task is
    seen having already run, indicating that all tasks after it have
    already been processed. Self-waking tasklets are no longer punished
    by sending them to the BULK queue (this happened with yielding
    tasks), and scheduler budgets were readjusted to match these
    changes. Additionally, tasklets are no longer automatically
    requeued into the current queue (that was a mistake that caused
    them to be marked as self-waking). Overall the observed average and
    peak latencies are now better, especially under heavy attacks.

  - HTTP/2: a limited frames processing budget was added for HTTP/2
    (tune.h2.be.max-frames-at-once, tune.h2.fe.max-frames-at-once,
    tune.h2.fe.max-rst-at-once) to prevent latency from large frame
    floods. These changes significantly improve processing latency
    under heavy H2 RST flood attacks and overall average loop times.
    Some tests showed that the maximum impact of some floods could be
    divided by 20 to 50 by just setting "tune.h2.fe.max-rst-at-once 1".

  - Lua's httpclient headers conversion accepted more than 101 headers
    without bound checking, causing a stack buffer overflow reachable
    from any Lua action/task/service.

  - Lua had a format-string vulnerability in pattern reference error
    paths, enabling ASLR/canary leaks or arbitrary writes via %n.

  - peers dictionary cache updates accepted an unvalidated entry id as
    array index, allowing OOB heap writes at attacker-controlled
    offsets.

  - a race condition in task scheduling could cause a BUG_ON() when
    task_schedule() sets expire while the task is already running. Very
    rare but reported by users (e.g. server configured with slowstart
    updating its weight at the same moment it goes up).

  - Lua had a use-after-free of HTTP reason strings managed by Lua's GC
    between set_status() and start_response(), potentially leaking adjacent
    information from memory.

  - the regsub sample function could leak ~9-50KB of stale heap data
    when back-reference expansion overflowed the output buffer.

  - SPOE decode_varint() had no iteration cap, allowing pointer
    arithmetic to wrap and dereference memory ~64KB before the
    allocation, causing SIGSEGV or parser confusion.

  - DNS AAAA additional records handling leaked ~580 bytes per response
    due to a leftover break statement after a switch-to-if/else
    conversion.

  - HTTP/1 bodyless responses (HEAD, 204, 304) were subject to a ~200ms
    TCP cork delay because MSG_MORE was unconditionally set when
    inherited from the upper layer. This notably affected H1 frontend
    to H2 backend setups.

  - zero-copy forwarding was not disabled when draining the request
    after an early response, preventing regular receives.

  - HTTP/2 connection liveness checks used conn->owner to decide if a
    connection was dead, which caused premature connection disposal
    when owner was NULL (fully idle connections after the last stream
    left), leading to connections being closed after each stream at low
    loads. Also, a fix introduced in 3.3.5 to report pending errors
    earlier was reverted since no longer necessary after recent HTX
    fixes.

  - the H1 null-chunk emission condition for bodyless messages was
    wrong, with the server-side flag being tested during request
    processing. For example a chunked response to a HEAD request could
    be sent without the null chunk. Additionally, the trailer skip test
    for chunked messages had its flags inverted between client and
    server sides.

  - HTX defrag used an incorrect function to change part of a block
    value when data expanded, causing old block data to become
    inaccessible after the move.

  - CLI commands with too-big payloads caused an infinite parse loop
    instead of returning an error, leaving the client stuck in prompt
    state.

  - in sample expressions, less common HTTP methods (PATCH etc.) are
    represented by both an enum and a string. The string part was not
    handled correctly in sample duplication functions, resulting in
    their contents appearing empty when trying to fetch the method.

  - peers expired entries were trashed later than expected after
    fullresync because tree reordering didn't move them back in past.

  - ACME had multiple small issues: resource leaks in x509 request
    generation (X509_NAME, str_san, X509_REQ, extensions), a leak of
    ext_san on insertion failure, wrong error messages for duplicate
    sections and argument counts, wrong argument check in 'acme renew',
    auth->dns leak in context destroy, errmsg leak from unconditional
    memprintf, DER buffer leak on base64url error path, atol() replaced
    with bounded __strl2uic() for retry-after parsing, task allocation
    leaked on failure, and a case where the client would not skip
    already-valid challenges causing cert issuance to fail. ACME now
    avoids passing NULL into format strings.

  - SPOE applet could hit BUG_ON() when copying frames into the context
    buffer without first allocating it. This was revealed by large
    buffer changes.

  - QUIC had several fixes: counters used on backend side referenced
    frontend counters (wrong stats for pure backends), HTML stats
    missing QUIC/H3 backend capability display, missing app ops init
    during backend 0-RTT session cache reuse failure causing mux crash,
    incompatible frames now properly close the connection with
    PROTOCOL_VIOLATION instead of being silently dropped, and stream
    IDs are now limited to 2^62 per the QUIC spec. QPACK varint
    decoding is now also limited to 62-bit, and had a risk of 1-byte
    OOB reads on truncated streams, which could cause incorrect header
    decoding.

  - dynamic servers now default to "sni-auto" and support "no-sni-auto" and
    "no-check-sni-auto" configuration keywords.

  - tcpcheck had several minor fixes: the parsing context for error
    reporting would wrongly be reported as server instead of TCP check,
    and using HTTP sample fetch functions would needlessly cause an
    HTTP transaction to be allocate for streams created on these
    proxies.
  
  - H2 protocol error counting was improved: trailer parse failures and
    stream rejection on parsing error now properly count as protocol
    errors. Previously they would be reported as internal errors. The
    parsing error counter on the connection and on the proxy are now
    updated. The tune.h2.log-errors setting introduced in 3.3.5 really
    works now (previously no errors were logged for any value except
    "none"). PRIORITY frame exclusive bit was properly masked from the
    stream ID check. shared_rx_bufs are now freed on H2 init failure,
    otherwise out of memory could cause memory leaks.
  
  - the stream connector (stconn) now sets a flag on the stream
    endpoint descriptor when the upper stream has started, which allows
    the H2 mux to detect whether an RST_STREAM applies to an already
    started stream or to one just seen, and report glitches in this
    later case, as it's symptomatic of an attack.
  
  - "compression direction response" preserved the request flag instead
    of clearing it during parsing, making it impossible to disable
    request compression if it was earlier enabled.
  
  - log-format sample fetch dependencies were refined: response and
    body dependencies are now considered so that timestamps, byte
    counts and volatile response headers are properly waited for. This
    is important when trying to log "req.bytes_in" or "res.bytes_in",
    which would previously not cause the log to wait till the end of
    the transfer, contrary to the %U/%B log-format aliases.
  
  - config: a few argument parsing errors in conditional expressions
    used in ".if" could be misreported and even cause a crash during
    the parsing. Also, a few keywords relying on warnif_misplaced_*
    didn't check the return value and didn't count emitted warnings as
    warnings.
  
  - abortonclose now only considers client aborts, not stream aborts,
    preventing yielding rules from being interrupted while the client
    still waits.
  
  - stats-file: inconsistent shared clocks when resuming from
    shm-stats-file are detected and corrected (adjusting when offset
    >60s). A future improvement that is still under validation in 3.4
    will even allow to remove that remaining limiation. GUID truncation
    for shm-stats-file objects was fixed to use full 128 chars.
  
  - the accept() error messages for ENFILE and ENOMEM now print actconn
    instead of global.maxsock which doesn't reflect system limits.
  
  - the 'show proc' command now displays old workers in the correct order
    (newest first).
  
  - a stream created from healthchecks was not flagged as a backend
    connection. It doesn't seem to have had impacts, though maybe some error
    counters could have been incorrectly reported.
  
  - threads: setting nbthreads above the maximum number of threads per group
    (64 or defined at build time) would silently lower the number to the
    number of threads fitting in the number of groups. Now it will properly
    adjust the number of groups. Those running with "nbthreads 128" were
    likely limited to 64 without noticing for example, and will now have
    128 threads running as if nbthreads hadn't been forced and they'd let
    the CPU topology code do its job.

Finally there were also a few very minor fixes such as the "pause"
action error message, an extra ']' in log-format error message, a wrong
check in the opentracing group filter parser, and an adjustment to
avoid suspecting uninitialized variable in code analysis. The rest is a
few doc updates, CI and regtest updates.

While I usually suggest to update only if needed, here I would say that
the number of areas covered by fixes is too broad to precisely know if
some affect your usage or not, so please just update your version.

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/3.3/src/
   Git repository   : https://git.haproxy.org/git/haproxy-3.3.git/
   Git Web browsing : https://git.haproxy.org/?p=haproxy-3.3.git
   Changelog        : https://www.haproxy.org/download/3.3/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

Willy
---
Complete changelog :
Amaury Denoyelle (10):
      BUG/MINOR: proxy: detect strdup error on server auto SNI
      BUG/MINOR: server: set auto SNI for dynamic servers
      BUG/MINOR: server: enable no-check-sni-auto for dynamic servers
      BUG/MINOR: quic: fix counters used on BE side
      BUG/MINOR: quic/h3: display QUIC/H3 backend module on HTML stats
      MINOR: ncbmbuf: improve itbmap_next() code
      BUG/MINOR: quic: close conn on packet reception with incompatible frame
      DOC: configuration: mention QUIC server support
      BUG/MINOR: quic: fix documentation for transport params decoding
      BUG/MINOR: mux_quic: limit avail_streams() to 2^62

Aurelien DARRAGON (5):
      BUG/MINOR: stats-file: manipulate shm-stats-file heartbeat using unsigned 
int
      BUG/MEDIUM: stats-file: detect and fix inconsistent shared clock when 
resuming from shm-stats-file
      DOC: config: fix ambiguous info in log-steps directive description
      BUG/MINOR: counters: fix unexpected 127 char GUID truncation for 
shm-stats-file objects
      BUG/MINOR: task: fix uninitialised read in run_tasks_from_lists()

Christopher Faulet (23):
      Revert "BUG/MEDIUM: mux-h2: make sure to always report pending errors to 
the stream"
      DOC: config: Fix alphabetical ordering of proxy options
      DOC: config: Fix alphabetical ordering of external-check directives
      DOC: config: Add missing 'status-code' param for 'http-check expect' 
directive
      DOC: config: Reorder params for 'tcp-check expect' directive
      BUG/MEDIUM: spoe: Acquire context buffer in applet before consuming a 
frame
      BUG/MINOR: config: Properly test warnif_misplaced_* return values
      BUG/MINOR: http-ana: Only consider client abort for abortonclose
      BUG/MINOR: stconn: Always declare the SC created from healthchecks as a 
back SC
      BUG/MINOR: tcpcheck: Remove unexpected flag on tcpcheck rules for httchck 
option
      BUG/MINOR: tcpcheck: Don't enable http_needed when parsing HTTP samples
      BUG/MINOR: tcpcheck: Use tcpcheck context for expressions parsing
      BUG/MEDIUM: mux-h1: Disable 0-copy forwarding when draining the request
      BUG/MEDIUM: samples: Fix handling of SMP_T_METH samples
      BUG/MEDIUM: cli: Properly handle too big payload on a command line
      BUG/MEDIUM: htx: Fix function used to change part of a block value when 
defrag
      BUG/MEDIUM: htx: Don't count delta twice when block value is replaced
      BUG/MINOR: mux-h1: Fix condition to send null-chunk for bodyless message
      BUG/MINOR: mux-h1: Fix test to skip trailers from chunked messages
      DOC: config: Fix a typo for "external-check" directive
      REGTESTS: Never reuse server connection in jwt/jws_verify.vtc
      REGTESTS: Never reuse server connection in 
server/cli_delete_dynamic_server.vtc
      BUG/MEDIUM: mux-h1: Force close mode for bodyless message announcing a C-L

Cody Ohlsen (1):
      BUG/MEDIUM: mux-h1: Don't set MSG_MORE on bodyless responses forwarded to 
client

David Carlier (1):
      BUG/MEDIUM: acme: fix multiple resource leaks in acme_x509_req()

Egor Shestakov (2):
      BUG/MINOR: sock: adjust accept() error messages for ENFILE and ENOMEM
      BUG/MINOR: acme: don't pass NULL into format string

Emeric Brun (1):
      BUG/MEDIUM: peers: trash of expired entries delayed after fullresync

Frederic Lecaille (2):
      BUG/MINOR: qpack: fix 62-bit overflow and 1-byte OOB reads in decoding
      BUG/MINOR: quic: missing app ops init during backend 0-RTT sessions

Greg Kroah-Hartman (11):
      BUG/MEDIUM: payload: validate SNI name_len in req.ssl_sni
      BUG/MEDIUM: jwt: fix heap overflow in ECDSA signature DER conversion
      BUG: hlua: fix stack overflow in httpclient headers conversion
      BUG/MINOR: hlua: fix stack overflow in httpclient headers conversion
      BUG/MINOR: hlua: fix format-string vulnerability in Patref error path
      BUG/MINOR: peers: fix OOB heap write in dictionary cache update
      BUG/MINOR: resolvers: fix memory leak on AAAA additional records
      BUG/MINOR: spoe: fix pointer arithmetic overflow in spoe_decode_buffer()
      BUG/MINOR: sample: fix info leak in regsub when exp_replace fails
      BUG/MEDIUM: mux-fcgi: prevent record-length truncation with large bufsize
      BUG/MINOR: hlua: fix use-after-free of HTTP reason string

Ilia Shipitsin (2):
      CI: github: fix tag listing by implementing proper API pagination
      reg-tests/ssl/ssl_dh.vtc: fix syntax error

Mia Kanashi (2):
      BUG/MINOR: acme: fix incorrect number of arguments allowed in config
      BUG/MEDIUM: acme: skip doing challenge if it is already valid

Miroslav Zagorac (1):
      BUG/MINOR: ot: fixed wrong NULL check in flt_ot_parse_cfg_group()

Olivier Houchard (4):
      BUG/MEDIUM: tasks: Make sure we don't schedule a task already running
      BUG/MINOR: h2: make tune.h2.log-errors actually work
      BUG/MINOR: h2: Don't look at the exclusive bit for PRIORITY frame
      BUG/MINOR: H2: Don't forget to free shared_rx_bufs on failure

Tim Duesterhus (1):
      BUG/MINOR: log: Fix error message when using unavailable fetch in logfmt

William Lallemand (23):
      BUG/MINOR: mworker: fix sort order of mworker_proc in 'show proc'
      BUG/MINOR: acme: leak of ext_san upon insertion error
      BUG/MINOR: acme: wrong error when checking for duplicate section
      BUG/MINOR: acme/cli: wrong argument check in 'acme renew'
      BUG/MINOR: acme: acme_ctx_destroy() leaks auth->dns
      BUG/MINOR: acme: wrong labels logic always memprintf errmsg
      BUG/MINOR: acme: free() DER buffer on a2base64url error path
      BUG/MINOR: acme: replace atol with len-bounded __strl2uic() for 
retry-after
      BUG/MINOR: acme/cli: fix argument check and error in 'acme 
challenge_ready'
      BUILD: tools: potential null pointer dereference in dl_collect_libs_cb
      BUG/MINOR: ech: permission checks on the CLI
      BUG/MINOR: acme: permission checks on the CLI
      BUG/MINOR: acme: fix task allocation leaked upon error
      BUG/MEDIUM: ssl/cli: tls-keys commands warn when accessed without admin 
level
      BUG/MEDIUM: ssl/ocsp: ocsp commands warn when accessed without admin level
      BUG/MEDIUM: map/cli: map/acl commands warn when accessed without admin 
level
      BUG/MEDIUM: ssl/cli: tls-keys commands are missing permission checks
      BUG/MEDIUM: ssl/ocsp: ocsp commands are missing permission checks
      BUG/MEDIUM: map/cli: CLI commands lack admin permission checks
      REGTESTS: ssl: mark ssl_dh.vtc as broken
      SCRIPTS: build-vtest: allow to set a TMPDIR and a DESTDIR
      CI: VTest build with git clone + cache
      CI: github: only enable OS X on development branches

Willy Tarreau (29):
      MEDIUM: sched: do not run a same task multiple times in series
      MINOR: sched: do not requeue a tasklet into the current queue
      MINOR: sched: do not punish self-waking tasklets anymore
      MEDIUM: sched: do not punish self-waking tasklets if TASK_WOKEN_ANY
      MEDIUM: sched: change scheduler budgets to lower TL_BULK
      MINOR: mux-h2: assign a limited frames processing budget
      BUILD: sched: fix leftover of debugging test in single-run changes
      MINOR: stconn: flag the stream endpoint descriptor when the app has 
started
      MINOR: mux-h2: report glitches on early RST_STREAM
      SCRIPTS: git-show-backports: list new commits and how to review them with 
-L
      BUG/MINOR: cfgcond: properly set the error pointer on evaluation error
      BUG/MINOR: cfgcond: always set the error string on openssl_version checks
      BUG/MINOR: cfgcond: always set the error string on awslc_api checks
      BUG/MINOR: cfgcond: fail cleanly on missing argument for "feature"
      BUG/MINOR: http-act: fix a typo in the "pause" action error message
      BUG/MAJOR: slz: always make sure to limit fixed output to less than worst 
case literals
      BUG/MINOR: threads: properly set the number of tgroups when non using 
policy
      BUG/MEDIUM: mux-h2: ignore conn->owner when deciding if a connection is 
dead
      BUG/MINOR: log: consider format expression dependencies to decide when to 
log
      MINOR: sample: make RQ/RS stats available everywhere
      BUG/MINOR: sample: adjust dependencies for channel output bytes counters
      BUG/MAJOR: sched: protect task->expire on 32-bit platforms
      BUG/MINOR: mux-h2: count a protocol error when failing to parse a trailer
      BUG/MINOR: mux-h2: count a proto error when rejecting a stream on parsing 
error
      BUG/MINOR: log: also wait for the response when logging response headers
      BUG/MINOR: compression: properly disable request when setting response
      BUG/MINOR: debug: properly mark the entire libs archive read-only
      BUG/MINOR: server: fix a possible leak of an error message in dynamic 
servers
      BUG/MAJOR: mux-h2: detect incomplete transfers on HEADERS frames as well

---


Reply via email to