Skip to content

[fix][sec][branch-4.x] Upgrade Netty to 4.1.138 to address several CVEs and bugs - #26515

Merged
nodece merged 1 commit into
apache:branch-4.2from
lhotari:lh-fix-netty-4.1.138
Sep 10, 2026
Merged

nodece merged 1 commit into
apache:branch-4.2from
lhotari:lh-fix-netty-4.1.138

Conversation

@lhotari

@lhotari lhotari commented Sep 10, 2026

Copy link
Copy Markdown
Member

Motivation

Netty 4.1.138.Final is a bug-fix and security
release, and upstream "strongly recommends" upgrading. This is the branch-4.2 counterpart of #26514,
which upgrades master to Netty 4.2.18.Final.

Security fixes. The release notes list 23 advisories, all shown as CVE-2026-XXXXX: upstream
states that "due to overwhelming strain on the CVE infrastructure, we have not gotten a single CVE
number assigned to these reports in time for our release. The advisories will be published without."
At the time of writing none of them have been published yet either — the newest advisory in
netty/netty's GitHub advisory database is still from 2026-08-07 — so there is nothing more specific
to link to. By affected artifact:

Netty artifact Advisories Bundled by Pulsar?
netty-codec-http (incl. SPDY / RTSP sub-codecs) 8 yes
netty-codec-http2 5 yes
netty-handler-ssl-ocsp 2 no
netty-codec-stomp 2 no
netty-codec-smtp 2 no
netty-codec-haproxy 1 yes
netty-codec-memcache 1 no
netty-codec-redis 1 no
netty-codec-mqtt 1 no

The categories are unbounded resource usage, denial of service, improper header validation, request
smuggling / parser desync, memory leaks, improper certificate validation and improper CRLF
neutralization.

The release notes also repeat that Netty 4.1 will be End-of-Life on July 1st, 2027.

Two upstream default changes are called out in the release notes. Neither affects Pulsar:

  • "HTTP/2 header value validation is now enabled by default." Pulsar has no direct use of Netty's
    HTTP/2 codec at all on this branch — searching every Java file for http2 / Http2FrameCodec /
    DefaultHttp2Headers / validateHeaders returns nothing. gRPC uses grpc-netty-shaded, which
    bundles its own relocated Netty, and unshaded grpc-netty is excluded in pom.xml.
    async-http-client 2.16.1 declares no netty-codec-http2 dependency at all; the jar reaches the
    distribution transitively via vertx-core, behind BookKeeper's VertxHttpServer, which
    conf/bookkeeper.conf:733 disables by default (httpServerEnabled=false). Beyond that, the
    newly-default check is the same rule Netty's HTTP/1 path has always enforced —
    DefaultHttp2Headers.HTTP2_VALUE_VALIDATOR and DefaultHttpHeadersFactory.DEFAULT_VALUE_VALIDATOR
    both delegate to HttpHeaderValidationUtil.validateValidHeaderValue, and those two HTTP/1 files
    are byte-identical between 4.1.137.Final and 4.1.138.Final — so it is a convergence rather than a
    new restriction.
  • "QUIC now explicitly requires X509ExtendedTrustManager when hostname verification is enabled."
    Pulsar does not use Netty's QUIC support and does not bundle any QUIC artifact.

Non-security fixes. 4.1.138.Final also carries fixes in areas Pulsar exercises:

  • Release unsent LastHttpContent in HttpChunkedInput (#17251)
  • HTTP/2: release compressors after failed headers writes (#17265); prevent reentrant flush on writability change (#17268); drain queued frames stranded by a writability change during flush (#17280)
  • HTTP: preserve encoder state after header encoding failures (#17275); release content encoder after header mutation failure (#17294)
  • Release channel when FixedChannelPool acquire is cancelled (#17291); close active unhealthy channels on release (#17319)
  • Close channel when connect is cancelled during resolution (#17349)
  • KQueue: continue reading when EOF is received before notifying about channel inactivity (#17309)
  • codec-dns: fix query OPCODE bit offset and mask (#17316); report and allow setting the full 16-bit EDNS(0) flags field (#17332)
  • Fix JdkZlibDecoder silently truncating highly compressible streams (#17364)
  • Bzip2: correctly detect overflow during block size bound check (#17273)
  • OCSP: add clock skew tolerance to OcspServerCertificateValidator (#17282)
  • Respect max messages per read in LocalServerChannel (#17269)

netty-tcnative. This branch does not pin netty-tcnative — it inherits it from the imported
netty-bom, so bumping <netty.version> alone moves it 2.0.81.Final → 2.0.84.Final
(netty-bom:4.1.138.Final declares <tcnative.version>2.0.84.Final</tcnative.version>). That
matters because the native engine is what most deployments actually run: tlsProvider is unset by
default (conf/broker.conf:854), DefaultPulsarSslFactory#buildNettySslContext then leaves the
provider null, and SecurityUtility passes that straight into
SslContextBuilder.sslProvider(null) — which makes Netty pick its own default, i.e. the native
OpenSSL engine whenever tcnative is available. The 24 commits across those three
releases

contain no BoringSSL change (boringsslCommitSha is byte-identical at
0226f30467f540a3f62ef48d453f93927da199b6 in both parent POMs) and no public API change
(javap -public over all of netty-tcnative-classes differs only in the JPMS module version
string). What they do contain are JNI/BIO memory-safety fixes on remote-peer-influenced paths:

  • Correctly handle wrap-around in the ring buffer used to buffer application data — a negative value
    cast to size_t fed to memcpy, i.e. a heap buffer overflow
  • Fix a use-after-free that could crash when session keys are rotated
  • SNI server_name decoding allowed an embedded NUL character (NewStringUTF → tcn_new_stringn)
  • Custom BIO_java_bytebuffer write callback over-reported bytes written, violating the BIO_write contract
  • JNI local-reference exhaustion while filling the signature-algorithm list, whose length is dictated by the remote peer (#995, #996)
  • *SSLPrivateKeyMethod did not report signing errors back correctly
  • Several NULL guards against SIGSEGV (#999, #1004, #1006, #1007)
  • Fix a double DeleteLocalRef (undefined behaviour) that #996 introduced in 2.0.82.Final (#1001) — going straight to 2.0.84.Final skips that window
  • Make the Linux artifacts loadable on musl (Alpine) again — relevant to Pulsar's official Docker image, which is Alpine-based and carries an LD_PRELOAD=/lib/libgcompat.so.0 workaround for exactly this class of breakage

Given the recent Conscrypt 2.6.2 glibc-floor incident, the Linux natives were checked explicitly: the
highest versioned reference is unchanged at GLIBC_2.12 (x86_64) and GLIBC_2.17 (aarch64), and the
DT_NEEDED list actually shrank — libgcc_s.so.1 and ld-linux-x86-64.so.2 are gone, because the
_Unwind_* family is now statically linked via libgcc_eh.a. The published classifier set is
unchanged, and the macOS minos (15.0) and Windows import set are unchanged too.

Modifications

  • pom.xml: <netty.version> 4.1.137.Final → 4.1.138.Final. netty-tcnative is intentionally not
    pinned here; it follows the netty-bom import, matching how the previous bump ([fix][sec][branch-4.2] Upgrade Netty to 4.1.137 to address several CVEs and bugs #26301) was done.
  • Update the bundled jar lists in distribution/server/src/assemble/LICENSE.bin.txt and
    distribution/shell/src/assemble/LICENSE.bin.txt to netty 4.1.138.Final and netty-tcnative
    2.0.84.Final

Netty's published module set is unchanged between 4.1.137.Final and 4.1.138.Final (the two
netty-bom module lists are identical), and none of the bundled Netty modules gained or lost a
dependency, so no LICENSE.bin.txt line had to be added or removed — only version strings changed.

Verifying this change

  • Make sure that the change passes the CI checks.

This change is already covered by existing tests. In addition, the resolution was verified out of
band with a standalone Maven project that imports netty-bom:4.1.138.Final exactly the way the root
pom.xml does: netty-tcnative-boringssl-static resolves to 2.0.84.Final together with all five
platform classifiers, and netty-tcnative-classes to 2.0.84.Final — matching the updated
LICENSE.bin.txt entries. Every one of the 27 Netty/tcnative jars named in the two
LICENSE.bin.txt files was confirmed present on Maven Central at the new versions.
src/check-binary-license.sh runs on both distributions in CI.

Does this pull request potentially affect one of the following parts:

If the box was checked, please highlight the changes

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

Netty is upgraded from 4.1.137.Final to 4.1.138.Final and netty-tcnative moves from 2.0.81.Final to
2.0.84.Final transitively via netty-bom.

…Es and bugs

Netty 4.1.138.Final is a bug-fix and security release which resolves 23
advisories across the HTTP, HTTP/2, STOMP, HAProxy, Memcache, Redis,
SMTP and MQTT codecs, plus the OCSP handler.

netty-tcnative moves 2.0.81.Final -> 2.0.84.Final transitively, since
netty-bom:4.1.138.Final declares tcnative.version 2.0.84.Final.

Assisted-by: Claude Code (Opus 5)
@nodece
nodece merged commit 32e8773 into apache:branch-4.2 Sep 10, 2026
53 checks passed
@lhotari lhotari added this to the 5.0.0-M2 milestone Sep 10, 2026
lhotari added a commit that referenced this pull request Sep 10, 2026
@lhotari lhotari removed this from the 5.0.0-M2 milestone Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants