Skip to content

[improve][misc] Upgrade Jetty to 12.1.12 - #26302

Merged
lhotari merged 3 commits into
apache:masterfrom
lhotari:lh-improve-jetty-12.1.12
Aug 10, 2026
Merged

lhotari merged 3 commits into
apache:masterfrom
lhotari:lh-improve-jetty-12.1.12

Conversation

@lhotari

@lhotari lhotari commented Aug 10, 2026 •

Copy link
Copy Markdown
Member

Motivation

Keep Pulsar on the latest Jetty 12.1.x patch release. Jetty 12.1.12 release notes: https://github.com/jetty/jetty.project/releases/tag/jetty-12.1.12

Regarding security fixes: no published Jetty security advisory lists 12.1.12 as its patched version. The most recent Jetty CVEs (CVE-2026-10050 and CVE-2026-10051) were already addressed in 12.1.10, which Pulsar upgraded to previously.

12.1.12 does contain a number of correctness fixes in areas that Pulsar exercises directly — the reverse proxy in pulsar-proxy (AdminProxyHandler extends ProxyServlet from jetty-ee10-proxy), the WebSocket endpoints in pulsar-websocket, and the ForwardedRequestCustomizer that the broker, proxy, WebSocket proxy and function worker all install for original-client-IP resolution:

Proxy response headers (jetty-ee10-proxy AbstractProxyServlet, used by AdminProxyHandler):

WebSocket:

  • Fix for a potential NPE when accessing HTTP headers after a WebSocket upgrade
  • Cleanups in RFC6455Handshaker and the WebSocket parser

HTTP:

Modifications

  • Bump jetty from 12.1.11 to 12.1.12 in gradle/libs.versions.toml

  • Update the Jetty artifact versions in distribution/server/src/assemble/LICENSE.bin.txt and distribution/shell/src/assemble/LICENSE.bin.txt

  • Update the OW2 ASM entries in distribution/server/src/assemble/LICENSE.bin.txt from 9.10 to 9.10.1: Jetty 12.1.12's jetty-annotations / jetty-ee10-annotations bring in the newer ASM transitively. Verified with ./gradlew :distribution:pulsar-server-distribution:dependencyInsight --configuration distLib --dependency org.ow2.asm:asm.

  • Initialize the AdminProxyHandler servlet in FunctionWorkerRoutingTest. The test called rewriteTarget() on a handler that was never initialized as a servlet. That worked until 12.1.12, where mime-type filtering by IncludeExclude should always be case-insensitive jetty/jetty.project#15496's companion change rewrote AbstractProxyServlet.validateDestination() to filter hosts through a single IncludeExclude; it now always dereferences the logger assigned by init(), whereas before it only did so when a whitelist/blacklist entry matched. The test consequently failed with an NPE on _log.

    This is a test-only gap, not a production regression: ProxyServiceStarter registers the handler through a ServletHolder, so the container calls init() and the logger is set. The test now initializes the servlet the same way and destroys it afterwards, which keeps the real validateDestination() path covered rather than working around it.

Verifying this change

  • Make sure that the change passes the CI checks.

This change is already covered by existing tests. Besides the full CI run, the following Jetty-facing tests were run locally against 12.1.12 and pass:

  • pulsar-proxy: the full module test suite (164 tests)
  • pulsar-broker: org.apache.pulsar.broker.web.* (including WebServiceTest and WebServiceOriginalClientIPTest, which covers the ForwardedRequestCustomizer path)
  • pulsar-websocket: the full module test suite
  • GzipHandlerUtilTest and PulsarAdminGzipTest

./gradlew checkBinaryLicense and ./gradlew sanityCheck also pass.

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

Keep Pulsar on the latest Jetty 12.1.x patch release. Release notes:
https://github.com/jetty/jetty.project/releases/tag/jetty-12.1.12

Jetty 12.1.12 pulls in ASM 9.10.1 (from 9.10) transitively via
jetty-annotations, so the OW2 ASM entries in the server LICENSE are
updated as well.
….1.12

# Conflicts:
#	gradle/libs.versions.toml
…rRoutingTest

FunctionWorkerRoutingTest called rewriteTarget() on an AdminProxyHandler that was
never initialized as a servlet. That happened to work until Jetty 12.1.12, where
AbstractProxyServlet.validateDestination() was rewritten to filter hosts through a
single IncludeExclude and now always dereferences the logger that init() assigns,
instead of only doing so when a whitelist or blacklist entry matched. The test
therefore failed with a NullPointerException on _log.

In production the servlet is registered through a ServletHolder in
ProxyServiceStarter, so the container calls init() and the logger is set; only the
test bypassed initialization. Initialize the servlet in the test the same way and
destroy it afterwards, so the real validateDestination() path stays covered.
@lhotari
lhotari merged commit 403aae6 into apache:master Aug 10, 2026
43 checks passed
lhotari added a commit that referenced this pull request Aug 10, 2026
lhotari added a commit that referenced this pull request Aug 10, 2026
nodece pushed a commit to ascentstream/pulsar that referenced this pull request Aug 28, 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