CVE-2026-118042
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Guava is a set of core Java libraries from Google that includes new collection types such as multimap and multiset, immutable collections, a graph library, and utilities for concurrency, I/O, hashing, primitives, and strings. It ships in two flavors distinguished by a version suffix: a JRE flavor requiring JDK 8 or higher, and an Android flavor. It is one of the most widely used third-party dependencies on the JVM.
A denial of service vulnerability (CVE-2026-118042) has been identified in Google Guava's HashBiMap and LinkedHashMultimap collections, which allows attackers to make building these collections take quadratic time by supplying keys or values whose hash codes collide. An application that fills one of these collections from untrusted input, such as header names, form fields or JSON keys, can be slowed down severely by a fairly small request.
Per OWASP: The Denial of Service (DoS) attack is focused on making a resource (site, application, server) unavailable for the purpose it was designed.
This issue affects multiple versions of Google Guava.
Details
Module Info
- Product: Google Guava
- Affected packages:
com.google.guava:guava - Affected versions: >=13.0, <=33.7.2-jre
- GitHub repository: https://github.com/google/guava
- Published packages: https://central.sonatype.com/artifact/com.google.guava/guava
- Package manager: Maven
- Fixed in:
- OSS Google Guava 33.8.0
- NES for Google Guava v31.0.4
Vulnerability Info
This Low-severity vulnerability is found in the com.google.guava:guava package in multiple versions of Google Guava. HashBiMap and the per-key value sets of LinkedHashMultimap (LinkedHashMultimap.ValueSet) use Guava's own chained hash tables rather than JDK collections, and those tables have no limit on how long a single bucket can grow and no fallback when one does. Other Guava hash structures (CompactHashMap, CompactHashSet and the immutable collections) and java.util.HashMap already defend against long buckets; these two do not.
In HashBiMap, every put first looks up the key by walking its whole bucket:
private BiEntry<K, V> seekByKey(@CheckForNull Object key, int keyHash) {
for (BiEntry<K, V> entry = hashTableKToV[keyHash & mask];
entry != null;
entry = entry.nextInKToVBucket) {
if (keyHash == entry.keyHash && Objects.equal(key, entry.key)) {
return entry;
}
}
return null;
}LinkedHashMultimap.ValueSet.add does the same for each value added under a key:
public boolean add(@ParametricNullness V value) {
int smearedHash = Hashing.smearedHash(value);
int bucket = smearedHash & mask();
ValueEntry<K, V> rowHead = hashTable[bucket];
for (ValueEntry<K, V> entry = rowHead; entry != null; entry = entry.nextInValueBucket) {
if (entry.matchesValue(value, smearedHash)) {
return false;
}
}
...
}When the inserted keys (or values) share a hashCode(), they all land in one bucket, so each insertion scans every earlier entry and building the collection takes quadratic time. Colliding strings are cheap to produce: "Aa" and "BB" have the same hash, so every concatenation of k such pairs collides, giving 2^k distinct keys. About 2 MB of input (65,536 keys of 32 characters) is enough to make a single HashBiMap or LinkedHashMultimap take several seconds to build, compared with a few milliseconds for HashMap.
Steps to Reproduce
- Add an affected version of
com.google.guava:guavato a Java project. - Run the following program, which inserts colliding string keys into a
HashMap, aHashBiMapand aLinkedHashMultimapand prints the time each takes:import com.google.common.collect.*; import java.util.*; public class Flood { static List<String> keys(int bits) { List<String> l = new ArrayList<>(); for (int i = 0; i < (1 << bits); i++) { StringBuilder s = new StringBuilder(); for (int b = 0; b < bits; b++) s.append(((i >> b) & 1) == 0 ? "Aa" : "BB"); l.add(s.toString()); } return l; } public static void main(String[] args) { for (int bits : new int[] {12, 14, 16}) { List<String> k = keys(bits); long t = System.nanoTime(); Map<String, Integer> m = new HashMap<>(); for (int i = 0; i < k.size(); i++) m.put(k.get(i), i); long hashMap = System.nanoTime() - t; t = System.nanoTime(); BiMap<String, Integer> b = HashBiMap.create(); for (int i = 0; i < k.size(); i++) b.put(k.get(i), i); long hashBiMap = System.nanoTime() - t; t = System.nanoTime(); SetMultimap<String, String> lm = LinkedHashMultimap.create(); for (String s : k) lm.put("x", s); long linkedHashMultimap = System.nanoTime() - t; System.out.printf( "n=%d HashMap=%dms HashBiMap=%dms LinkedHashMultimap=%dms%n", k.size(), hashMap / 1_000_000, hashBiMap / 1_000_000, linkedHashMultimap / 1_000_000); } } } - Observe that the
HashMaptime stays nearly flat while theHashBiMapandLinkedHashMultimaptimes grow quadratically, reaching several seconds at n=65536.
Mitigation
Only recent versions of Google Guava are community-supported. Only the recent community supported version will receive updates to address this issue. For more information, see here.
Users of the affected components should apply one of the following mitigations:
- Upgrade affected applications to supported versions of Google Guava.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- arshsmith1 (finder)