Skip to content

[fix][sec] Upgrade Netty to 4.2.18 to address several CVEs and bugs - #26514

Merged
nodece merged 1 commit into
apache:masterfrom
lhotari:lh-fix-netty-4.2.18
Sep 10, 2026
Merged

nodece merged 1 commit into
apache:masterfrom
lhotari:lh-fix-netty-4.2.18

Conversation

@lhotari

@lhotari lhotari commented Sep 10, 2026

Copy link
Copy Markdown
Member

Motivation

Netty 4.2.18.Final is a bug-fix and security
release, and upstream "strongly recommends" upgrading.

Security fixes. The release notes list 30 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-http3 6 no
netty-codec-http2 4 yes
netty-codec-http2 + netty-codec-http3 1 partly
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
netty-codec-classes-quic 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.

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 — searching all 4619 Java files for http2 / Http2FrameCodec /
    DefaultHttp2Headers / validateHeaders returns nothing. The codec is on the classpath only
    because async-http-client depends on it, and Pulsar's primary HTTPS clients
    (PulsarAdmin's HttpClient, AsyncHttpConnector, FrameworkHttpClientFactory) install a custom
    SslEngineFactory built from TlsContexts.buildNettyClientContext, which never calls
    applicationProtocolConfig, so ALPN never advertises h2 and HTTP/2 is never negotiated. 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 — 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 netty-codec-classes-quic.

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

  • io_uring: do not release write memory that the kernel still owns (#17238) — a use-after-free on the io_uring write path
  • Release unsent LastHttpContent in HttpChunkedInput (#17240)
  • HTTP/2: release compressors after failed headers writes (#17253); prevent reentrant flush on writability change (#17266); drain queued frames stranded by a writability change during flush (#17279)
  • HTTP: preserve encoder state after header encoding failures (#17271); release content encoder after header mutation failure (#17292)
  • Fix NPE in AbstractNioChannel.removeReadOp() after concurrent deregistration (#17104)
  • Release channel when FixedChannelPool acquire is cancelled (#17287); close active unhealthy channels on release (#17306)
  • Close channel when connect is cancelled during resolution (#17321)
  • codec-dns: fix query OPCODE bit offset and mask (#17314); report and allow setting the full 16-bit EDNS(0) flags field (#17325)
  • Fix JdkZlibDecoder (#17370) and JZlibDecoder (#17392) silently truncating highly compressible streams
  • Bzip2: correctly detect overflow during block size bound check (#17261)
  • Use VarHandle JCTools queues without Unsafe (#17185)
  • Add a system property to disable RFC 6761 localhost resolution (#17100)

netty-tcnative. Bumped 2.0.81.Final → 2.0.84.Final to stay aligned with what
netty-parent:4.2.18.Final itself declares (<tcnative.version>2.0.84.Final</tcnative.version>).
This matters because Pulsar defaults to the native TLS engine — TlsFactorySupport and
ClientTlsFactorySupport both resolve an unset tlsProvider to SslProvider.OPENSSL_REFCNT
whenever OpenSsl.isAvailable() — so broker, proxy and client TLS all run through this code by
default. 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 (#26315), 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

  • gradle/libs.versions.toml: netty 4.2.17.Final → 4.2.18.Final, netty-tcnative 2.0.81.Final → 2.0.84.Final
  • Update the bundled jar lists in distribution/server/src/assemble/LICENSE.bin.txt and
    distribution/shell/src/assemble/LICENSE.bin.txt to the new versions

Netty's published module set is unchanged between 4.2.17.Final and 4.2.18.Final, 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, ./gradlew checkBinaryLicense was run
locally for both the server and shell distributions (the shell one with --rerun) to confirm the
LICENSE.bin.txt entries match the jars that are actually bundled, and ./gradlew quickCheck
passes.

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.2.17.Final to 4.2.18.Final and netty-tcnative from 2.0.81.Final to
2.0.84.Final.

Netty 4.2.18.Final is a bug-fix and security release which resolves 30
advisories across the HTTP, HTTP/2, HTTP/3, STOMP, HAProxy, Memcache,
Redis, SMTP and MQTT codecs, plus the OCSP and QUIC handlers.

netty-tcnative is bumped 2.0.81.Final -> 2.0.84.Final to stay aligned
with what netty-parent:4.2.18.Final declares.

Assisted-by: Claude Code (Opus 5)
@nodece
nodece merged commit 7ddeac8 into apache:master Sep 10, 2026
43 checks passed
@lhotari lhotari added this to the 5.0.0-M2 milestone Sep 10, 2026
dao-jun added a commit to ascentstream/pulsar that referenced this pull request Sep 20, 2026
…pache#26514)

Port of the upstream netty 4.2.17.Final -> 4.2.18.Final upgrade:
- root pom netty.version bump; netty-tcnative follows via the netty-bom
  (2.0.81.Final -> 2.0.84.Final)
- LICENSE.bin.txt (server + shell) netty/tcnative version lines realigned
  with the bundled jars
- ProxyProtocolTest.testSniProxyProtocol: use unresolvable-broker-address
  in the broker service URL so it matches the certificate SAN, as required
  by the now default-on hostname verification (same change as upstream
  PIP-478 core migration apache#26282)

Fixes the TLS handshake failures ("Connection already closed") seen with
netty 4.2.17 in ProxyServiceTlsStarterTest / ProxyProtocolTest.

(cherry picked from commit 7ddeac8e2339f3bd2b9e7c1d3694ec7c1a820bdc)
dao-jun added a commit to ascentstream/pulsar that referenced this pull request Sep 20, 2026
…pache#26514)

Port of the upstream netty 4.2.17.Final -> 4.2.18.Final upgrade:
- root pom netty.version bump; netty-tcnative follows via the netty-bom
  (2.0.81.Final -> 2.0.84.Final)
- LICENSE.bin.txt (server + shell) netty/tcnative version lines realigned
  with the bundled jars
- ProxyProtocolTest.testSniProxyProtocol: use unresolvable-broker-address
  in the broker service URL so it matches the certificate SAN, as required
  by the now default-on hostname verification (same change as upstream
  PIP-478 core migration apache#26282)

Fixes the TLS handshake failures ("Connection already closed") seen with
netty 4.2.17 in ProxyServiceTlsStarterTest / ProxyProtocolTest.

(cherry picked from commit 7ddeac8e2339f3bd2b9e7c1d3694ec7c1a820bdc)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants