Skip to content

[fix][sec][branch-4.x] Upgrade lz4-java to 1.11.2 - #26439

Merged
Technoboy- merged 1 commit into
apache:branch-4.2from
lhotari:lh-fix-lz4java-1.11.2-42
Aug 31, 2026
Merged

[fix][sec][branch-4.x] Upgrade lz4-java to 1.11.2#26439
Technoboy- merged 1 commit into
apache:branch-4.2from
lhotari:lh-fix-lz4java-1.11.2-42

Conversation

@lhotari

@lhotari lhotari commented Aug 31, 2026

Copy link
Copy Markdown
Member

Motivation

lz4-java 1.11.2 is a security-only release that fixes two unvalidated-allocation
(CWE-789) issues, both moderate, both CVSS 5.3
(CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L), both affecting
at.yawk.lz4:lz4-java <= 1.11.1:

  • GHSA-6cx8-rjf8-pr8g
    LZ4DecompressorWithLength.decompress(byte[], int) reads the 4-byte little-endian
    decompressed-length header via getDecompressedLength() and passes it straight to
    LZ4FastDecompressor.decompress(byte[], int, int), which does new byte[destLen]
    before reading a single byte of payload. getDecompressedLength() performs no
    validation at all — no bound against src.length, no ceiling, no rejection of
    negatives — so a 5-byte input can force up to a 2 GiB allocation per call.
    LZ4SafeDecompressor.decompress(byte[], int, int, int) has the same shape via
    maxDestLen.
  • GHSA-4v53-57pg-c464
    LZ4BlockInputStream.refill() grows its compressed-input buffer to the
    attacker-controlled compressedLen taken from the legacy LZ4Block header before
    reading the payload, so a header-only input can trigger a near-2 GiB allocation.

Neither advisory has a CVE assigned; both are repository-level advisories published
2026-08-06 and are only reachable through
/repos/yawkat/lz4-java/security-advisories, not the global advisory database.

Exposure in Pulsar is limited, but the vulnerable jar does ship. Pulsar's own LZ4
codec (CompressionCodecLZ4) uses aircompressor, not lz4-java, and no Pulsar
production code calls the affected decompressor APIs — pulsar-common declares
lz4-java at test scope only, for the CompressionCodecLZ4JNI reference codec.
However at.yawk.lz4:lz4-java reaches the server distribution transitively via
BookKeeper's distributedlog-common, so lib/at.yawk.lz4-lz4-java-1.11.1.jar is
bundled in the release tarball and is reported by dependency scanners.

master is already on 1.11.2 (gradle/libs.versions.toml); this is the branch-4.x
port. branch-4.0 is also on 1.11.1 and takes the same patch.

Modifications

  • pom.xml — bump lz4java.version from 1.11.1 to 1.11.2. The
    dependencyManagement entry for at.yawk.lz4:lz4-java uses this property, so it also
    pins the transitive BookKeeper/distributedlog resolution.
  • distribution/server/src/assemble/LICENSE.bin.txt — update the bundled jar name to
    at.yawk.lz4-lz4-java-1.11.2.jar.

Upstream 1.11.2 is a security patch plus 23 Renovate dependency/plugin updates
(v1.11.1...v1.11.2).

One upstream behaviour change is worth calling out: per GHSA-4v53-57pg-c464, 1.11.2
now rejects LZ4 blocks whose compressed length exceeds the uncompressed length. A
canonical LZ4BlockOutputStream never emits such a block — it writes
COMPRESSION_METHOD_RAW instead — so this only rejects non-canonical input. The new
acceptOversizedBlocks flag restores the old behaviour but reintroduces the DoS
vector. Pulsar does not use LZ4BlockInputStream/LZ4BlockOutputStream, so this does
not affect Pulsar's on-the-wire format.

Verifying this change

  • Make sure that the change passes the CI checks.

This change is a dependency upgrade without new test coverage; it is covered by
existing tests.

Verified locally:

  • The jar contents are unchanged in shape between 1.11.1 and 1.11.2: the set of
    .class and bundled native library (.so/.dylib/.dll) entries is identical,
    and the set of artifacts referenced by the published POM is identical — no public
    API change, no new transitive dependency.
  • The new version resolves everywhere it is used:
$ mvn -ntp dependency:tree -pl pulsar-common,pulsar-functions/worker,pulsar-package-management/bookkeeper-storage -Dincludes=at.yawk.lz4:lz4-java
[INFO] Building Pulsar Common 4.2.5-SNAPSHOT                              [1/3]
[INFO] \- at.yawk.lz4:lz4-java:jar:1.11.2:test
[INFO] Building Pulsar Functions :: Worker 4.2.5-SNAPSHOT                 [2/3]
[INFO]          \- at.yawk.lz4:lz4-java:jar:1.11.2:compile
[INFO] Building Apache Pulsar :: Package Management :: BookKeeper Storage 4.2.5-SNAPSHOT [3/3]
[INFO]          \- at.yawk.lz4:lz4-java:jar:1.11.2:compile
[INFO] BUILD SUCCESS
  • The downloaded lz4-java-1.11.2.jar SHA-1 matches the checksum published on Maven
    Central.
  • The updated LICENSE.bin.txt entry is validated in CI by
    src/check-binary-license.sh against the assembled server tarball.

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

Upgrades at.yawk.lz4:lz4-java from 1.11.1 to 1.11.2, a security-only
release that fixes two moderate (CVSS 5.3, CWE-789) unvalidated
allocation issues:

- GHSA-6cx8-rjf8-pr8g: LZ4DecompressorWithLength.decompress(byte[], int)
  passes the unvalidated 4-byte length header straight to
  LZ4FastDecompressor.decompress(byte[], int, int), which allocates the
  declared size before reading any payload. A 5-byte input can force up
  to a 2 GiB allocation.
- GHSA-4v53-57pg-c464: LZ4BlockInputStream.refill() grows its input
  buffer to the attacker-controlled compressedLen from the block header
  before reading the payload.

master is already on 1.11.2; this is the branch-4.x port.

Release notes: https://github.com/yawkat/lz4-java/releases/tag/v1.11.2
@Technoboy-
Technoboy- merged commit cead5fc into apache:branch-4.2 Aug 31, 2026
50 checks passed
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