Various lz4-java compression and decompression implementations do not guard against out-of-bounds memory access. Untrusted input may lead to denial of service and information disclosure.
Vulnerable Maven coordinates:
org.lz4:lz4-java up to and including 1.8.0
org.lz4:lz4-pure-java up to and including 1.8.0
net.jpountz.lz4:lz4 up to and including 1.8.0
Rating: High - 8.8
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:H/SC:N/SI:N/SA:N
CWE-125: Out-of-bounds Read
lz4-java provides a matrix of compression and decompression algorithms:
A JNI-based implementation based on the lz4 library (LZ4Factory.nativeInstance(), LZ4Factory.fastestInstance())
A Java implementation using the deprecated sun.misc.Unsafe API (LZ4Factory.unsafeInstance(), LZ4Factory.fastestInstance(), LZ4Factory.fastestJavaInstance())
A Java implementation without sun.misc.Unsafe (LZ4Factory.safeInstance())
Each of these variants has:
A "fast" decompressor
A "safe" decompressor
Compressors for various compression levels
The JNI "fast" decompressor is based on the LZ4_decompress_fast API of the lz4 C library. This function is deprecated because it lacks bounds checks and is insecure on untrusted input. Other JNI-based APIs (the safe decompressor and the compressors) are not vulnerable.
All Java-based implementations lack sufficient bounds checks. For the sun.misc.Unsafe-based implementations, this can lead to denial of service and information disclosure. For the normal Java implementations, this only leads to ArrayIndexOutOfBoundsExceptions and is not a vulnerability.
The vulnerability can be resolved without patching:
Applications using LZ4Factory.nativeInstance() in conjunction with .fastDecompressor() can switch to .safeInstance() in the short term. In the long term, it is recommended to switch to .safeDecompressor(), which is not vulnerable and provides better performance (despite the name).
Applications using LZ4Factory.unsafeInstance(), .fastestInstance() or .fastestJavaInstance() (Unsafe-based implementations) can switch to .safeInstance().
Because the maintainer of the official lz4-java library is unavailable, the lz4 organization has decided to discontinue the project.
A community-maintained fork of lz4-java is available at https://github.com/yawkat/lz4-java. Two new versions have been released.
at.yawk.lz4:lz4-java:1.8.1 implements the workarounds listed above. The JNI-based fast decompressor is replaced with the safe Java implementation. All sun.misc.Unsafe-based compressors and decompressors are replaced with their safe counterparts. New unsafeInsecureInstance and nativeInsecureInstance factory methods were added for the insecure implementations for applications that operate on trusted input only. This version is directly based on 1.8.0 and only includes the minimum changes necessary to fix the vulnerability.
at.yawk.lz4:lz4-java:1.9.0 adds a reworked build system, updates to the underlying lz4 library (not security-related), and various fixes for the Java implementations. The changes from 1.8.1 remain. The Unsafe-based implementation may be made available by default again in a future release, once there is confidence in the security of the patched implementation.
org.lz4:lz4-java:1.8.1 is a relocation pom pointing to at.yawk.lz4:lz4-java:1.8.1, provided by Sonatype. Users that upgrade to the former coordinates will get the latter artifact, and a warning to update their maven coordinates. Future releases (including 1.9.0) will only be published under the at.yawk.lz4 group ID.
Jonas Konrad (Oracle corp.): Discovery and patch
Marcono1234: Patch and review
Sonatype: Disclosure coordination; Relocation pom