Skip to main content
Vulnerability Database/CVE-2026-90852

CVE-2026-90852: luben zstd-jni Use After Free Vulnerability

CVE-2026-90852 is a use after free vulnerability in luben zstd-jni library affecting the ZstdCompressCtx.loadDict function. Attackers can exploit this remotely to compromise system stability. This article covers technical details, affected versions, impact assessment, and mitigation strategies.

Published:

CVE-2026-90852 Overview

CVE-2026-90852 is a use-after-free vulnerability in the luben zstd-jni library, a Java Native Interface (JNI) binding for the Zstandard compression library. The flaw affects the ZstdCompressCtx.loadDict function in ZstdCompressCtx.java within the Dictionary Sharing component. Versions up to and including 1.5.7-13 are affected. The vulnerability stems from incorrect lifetime tracking between shared dictionary objects and compression contexts. An attacker can trigger the condition remotely when the library processes attacker-influenced compression workloads. The maintainer released a fix in version 1.5.7-14, identified by patch commit a560131d7834598afd9cea6b7c107bc88e915936.

Critical Impact

Remote exploitation of the use-after-free condition can lead to memory corruption impacting confidentiality, integrity, and availability of applications embedding vulnerable versions of zstd-jni.

Affected Products

  • luben zstd-jni versions up to and including 1.5.7-13
  • The ZstdCompressCtx.loadDict function in ZstdCompressCtx.java
  • Dictionary Sharing component of zstd-jni

Discovery Timeline

  • 2026-09-15 - CVE CVE-2026-90852 published to NVD
  • 2026-09-15 - Last updated in NVD database

Technical Details for CVE-2026-90852

Vulnerability Analysis

The vulnerability is classified under [CWE-119] (Improper Restriction of Operations within the Bounds of a Memory Buffer) and manifests as a use-after-free in the Dictionary Sharing subsystem of zstd-jni. When a compression context loads a dictionary via ZstdCompressCtx.loadDict, the shared lock accounting on the dictionary object is released prematurely relative to the compression context's usage. If the dictionary is closed or garbage collected while a compression context still holds a native reference to it, the underlying native memory can be freed while still in use. Subsequent compression operations then dereference freed memory, leading to memory corruption. Because zstd-jni is widely embedded in JVM-based data pipelines, message brokers, and storage engines, remote inputs that trigger dictionary handling can reach this code path from the network.

Root Cause

The root cause is incorrect cross-object lifetime tracking between AutoCloseBase-derived dictionaries and compression contexts. The SHARED_LOCK_UPDATER compare-and-set logic in AutoCloseBase.java treated the shared lock as a single-owner flag rather than a reference counter. Combined with ZstdCompressCtx.loadDict releasing the shared lock on the new dictionary before assigning it to the persistent compression_dict field, the accounting could reach zero while a live reference remained.

Attack Vector

The attack is network-reachable and requires no authentication or user interaction. An adversary who can influence compression dictionary handling in an application using vulnerable zstd-jni can trigger the free-then-use sequence, corrupting the JVM's native heap.

java
// Security patch in src/main/java/com/github/luben/zstd/ZstdCompressCtx.java
            if (Zstd.isError(result)) {
                throw new ZstdException(result);
            }
+           if (compression_dict != null) {
+               compression_dict.releaseSharedLock();
+           }
            // keep a reference to the dictionary so it's not garbage collected
            compression_dict = dict;
        } finally {
-           if (dict != null) {
-               dict.releaseSharedLock();
-           }
            releaseSharedLock();
        }
        return this;
// Source: https://github.com/luben/zstd-jni/commit/a560131d7834598afd9cea6b7c107bc88e915936

A companion change in AutoCloseBase.java converts the shared lock into a proper reference count:

java
// Security patch in src/main/java/com/github/luben/zstd/AutoCloseBase.java
            if (sharedLock == SHARED_LOCK_CLOSED) {
                return;
            }
-           if (!SHARED_LOCK_UPDATER.compareAndSet(this, 0, SHARED_LOCK_CLOSED)) {
-               throw new IllegalStateException("Attempt to close while in use");
+           if (sharedLock > 0) {
+               if (SHARED_LOCK_UPDATER.compareAndSet(this, sharedLock, sharedLock - 1)) {
+                   if (sharedLock == 0) {
+                       doClose();
+                   }
+               }
            }
-           doClose();
        }
// Source: https://github.com/luben/zstd-jni/commit/a560131d7834598afd9cea6b7c107bc88e915936

Detection Methods for CVE-2026-90852

Indicators of Compromise

  • JVM crash logs (hs_err_pid*.log) referencing native frames inside libzstd-jni or ZSTD_compress* functions.
  • Unexpected SIGSEGV or EXCEPTION_ACCESS_VIOLATION faults in Java processes performing Zstandard compression with dictionaries.
  • Application logs showing IllegalStateException: Attempt to close while in use on AutoCloseBase-derived objects prior to patching.

Detection Strategies

  • Inventory JVM applications and dependencies for com.github.luben:zstd-jni versions at or below 1.5.7-13 using software composition analysis (SCA) tooling.
  • Scan container images and build artifacts for the vulnerable zstd-jni JAR fingerprint and flag any deployments referencing pre-1.5.7-14 releases.
  • Correlate JVM crash telemetry with active use of ZstdDictCompress or ZstdCompressCtx.loadDict code paths in application traces.

Monitoring Recommendations

  • Enable JVM crash reporting and forward hs_err_pid*.log files to a centralized log platform for review.
  • Monitor process stability metrics for Java services that ingest attacker-influenced data through compression pipelines.
  • Track dependency updates in CI/CD to alert on any regression to zstd-jni versions prior to 1.5.7-14.

How to Mitigate CVE-2026-90852

Immediate Actions Required

  • Upgrade com.github.luben:zstd-jni to version 1.5.7-14 or later across all applications, containers, and build pipelines.
  • Rebuild and redeploy shaded or fat JARs that bundle zstd-jni to ensure the patched version is actually loaded at runtime.
  • Audit third-party libraries and platforms that transitively depend on zstd-jni and apply vendor updates as they become available.

Patch Information

The fix is available in GitHub Release v1.5.7-14 and corresponds to commit a560131d. The patch corrects cross-object lifetime tracking between dictionaries and compression contexts by converting the shared lock into a reference count and reordering the releaseSharedLock call in ZstdCompressCtx.loadDict. Additional context is documented in GitHub Issue #404 and the VulDB entry for CVE-2026-90852.

Workarounds

  • Avoid loading Zstandard dictionaries from untrusted or network-derived sources until the patched version is deployed.
  • Where feasible, disable dictionary-based compression in application configuration and fall back to dictionary-less Zstandard streams.
  • Isolate services that rely on zstd-jni behind trust boundaries so that only vetted inputs reach the compression path.
bash
# Maven dependency update to the patched release
# pom.xml
<dependency>
    <groupId>com.github.luben</groupId>
    <artifactId>zstd-jni</artifactId>
    <version>1.5.7-14</version>
</dependency>

# Gradle dependency update
# build.gradle
implementation 'com.github.luben:zstd-jni:1.5.7-14'

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.