CVE-2026-87795 Overview
CVE-2026-87795 is an out-of-bounds read vulnerability [CWE-125] in zstd-jni, the Java Native Interface (JNI) bindings for the Zstandard compression library. Versions from 1.2.0 through 1.5.7-13 fail to validate offset and length parameters passed to the ZstdDictCompress constructor. Attackers who control these values can read native heap memory into the compression dictionary, typically causing Java Virtual Machine (JVM) crashes. The issue is fixed in zstd-jni version 1.5.7-14.
Critical Impact
Untrusted callers can trigger out-of-bounds reads of native heap memory through ZstdDictCompress, causing JVM crashes and denial of service in applications that expose dictionary construction to untrusted input.
Affected Products
- zstd-jni versions 1.2.0 through 1.5.7-13
- Java applications embedding vulnerable zstd-jni releases
- Downstream libraries that expose ZstdDictCompress to untrusted callers
Discovery Timeline
- 2026-09-09 - CVE-2026-87795 published to the National Vulnerability Database (NVD)
- 2026-09-09 - Last updated in NVD database
Technical Details for CVE-2026-87795
Vulnerability Analysis
The flaw is located in the ZstdDictCompress constructor in the com.github.luben.zstd package. The constructor accepts a byte[] dict buffer along with integer offset and length values, then forwards them to a native init method implemented in jni_fast_zstd.c. Prior to 1.5.7-14, the Java layer only checked that dict.length - offset was non-negative and did not validate offset or length independently.
As a result, negative offset values or a length exceeding dict.length - offset were passed unchecked into the native layer. The native code then copied bytes from an attacker-controlled location relative to the pinned Java array into the ZSTD dictionary structure. This reads memory outside the intended buffer, corrupting internal compression state and typically terminating the JVM process.
Root Cause
The root cause is missing input validation on numeric parameters at the Java-to-native boundary. The constructor trusted the caller to provide sane offset and length values before invoking JNI code that performs unchecked pointer arithmetic on native heap memory.
Attack Vector
Exploitation requires an attacker to control the offset or length arguments passed to ZstdDictCompress. This most commonly occurs in services that build compression dictionaries from user-supplied metadata, network protocols that negotiate dictionary parameters, or higher-level libraries that forward untrusted values into zstd-jni. Successful exploitation causes an out-of-bounds read, resulting in a JVM crash and loss of service availability.
// Patch: src/main/java/com/github/luben/zstd/ZstdDictCompress.java
// Adds explicit bounds checks before invoking the native init() method
if (dict.length - offset < 0) {
throw new IllegalArgumentException("Dictionary buffer is too short");
}
if (offset < 0 || length < 0 || length > dict.length - offset) {
throw new IllegalArgumentException("Invalid offset/length for dictionary buffer");
}
init(dict, offset, length, level);
if (0 == nativePtr) {
// ...
}
// Source: https://github.com/luben/zstd-jni/commit/0d64de4dee6606ff506be36c7f2e714ad0c80fdb
Detection Methods for CVE-2026-87795
Indicators of Compromise
- Unexpected JVM crashes with SIGSEGV fatal error logs referencing libzstd-jni or Java_com_github_luben_zstd_ZstdDictCompress_init
- hs_err_pid*.log crash files containing stack frames inside jni_fast_zstd.c
- Repeated abnormal termination of services that build ZSTD dictionaries from network or user input
Detection Strategies
- Inventory Java applications and container images for zstd-jni versions between 1.2.0 and 1.5.7-13 using software composition analysis tooling
- Inspect Maven and Gradle dependency trees for transitive references to vulnerable zstd-jni artifacts
- Enable core dump collection on JVM processes handling untrusted compression input to capture evidence of native crashes
Monitoring Recommendations
- Alert on repeated JVM process restarts or crash loops on services that use zstd-jni
- Monitor application logs for IllegalArgumentException messages referencing dictionary buffer validation after upgrading
- Track denial-of-service patterns targeting endpoints that accept compressed payloads or dictionary metadata
How to Mitigate CVE-2026-87795
Immediate Actions Required
- Upgrade zstd-jni to version 1.5.7-14 or later across all Java applications and container images
- Audit code paths that instantiate ZstdDictCompress and confirm offset and length values are derived from trusted sources
- Rebuild and redeploy downstream libraries that shade or repackage zstd-jni to ensure they pull the patched release
Patch Information
The fix is delivered in the GitHub Release v1.5.7-14. The relevant changes appear in GitHub Commit 0d64de4, which adds explicit bounds validation in the ZstdDictCompress constructor and hardens AutoCloseBase.close() behavior. Additional context is available in GitHub Security Advisory GHSA-ff36-7w3w-g8rm and the VulnCheck zstd-jni Advisory.
Workarounds
- Validate offset and length parameters in application code before passing them to ZstdDictCompress, rejecting negative values and values exceeding dict.length - offset
- Restrict exposure of dictionary construction APIs to trusted internal callers only
- Isolate JVM workers that process untrusted compressed input so that crashes do not affect other tenants
# Maven: pin zstd-jni to the patched release
mvn versions:use-dep-version -Dincludes=com.github.luben:zstd-jni -DdepVersion=1.5.7-14 -DforceVersion=true
# Gradle: enforce the patched version in build.gradle
# dependencies {
# implementation('com.github.luben:zstd-jni:1.5.7-14')
# }
# Verify no vulnerable version remains on the classpath
find . -name 'zstd-jni-*.jar' -print
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.