CVE-2026-102554 is a denial-of-service vulnerability in Google Guava’s Java deserialization logic. A crafted serialization stream can declare an extremely large collection size before supplying only a small amount of real data. Affected Guava classes may then allocate arrays based on that attacker-controlled value and exhaust the JVM heap.
The practical response is not limited to changing a version in a build file. Teams need to find direct and transitive Guava copies, identify shaded or bundled JARs, confirm which version is running in production, and determine whether untrusted data can reach Java native deserialization.
The short answer
| سؤال | Answer |
|---|---|
| Affected package | com.google.guava:guava |
| الإصدارات المتأثرة | 4.0 through 33.7.1 |
| First patched version | 33.7.2 |
| Affected code paths | CompactHashMap, CompactHashSet, MapMakerInternalMap and inheriting compact linked collections during Java deserialization |
| التأثير الأساسي | JVM memory exhaustion and service denial of service |
| Important prerequisite | Attacker-controlled or insufficiently filtered Java serialization data reaches ObjectInputStream deserialization with affected Guava classes available |
| الإجراء الموصى به | Upgrade every deployed copy to 33.7.2 or later and audit deserialization reachability |
Google’s CVE record assigns CVSS 4.0 score 8.2, while the reviewed GitHub advisory also publishes a CVSS 3.1 score of 5.9. The difference reflects scoring-model treatment of the attack requirement. It does not change the remediation decision: a remotely reachable native-deserialization boundary should not retain an affected version.
What the vulnerable code does
CompactHashMap and CompactHashSet serialize an element count. During deserialization, affected versions accept any non-negative count and use it as the expected size. The first real insertion can then allocate the backing table and arrays for the declared size, even if the stream contains only one small object.
MapMakerInternalMap follows the same dangerous pattern through an initial-capacity value read from the stream. The value can influence segment-table allocation before the stream has demonstrated that it contains the claimed number of entries.
This is a resource-amplification problem. A small input can request a disproportionately large heap allocation. The resulting OutOfMemoryError can terminate the request, destabilize the process, or crash a service depending on JVM behavior and application error handling.
The advisory concerns Java native serialization. JSON parsing, ordinary map construction, and Guava collection use without ObjectInputStream are not the vulnerable operation described by this CVE.
What changed in Guava 33.7.2
إن fix commit is small and operationally meaningful. Guava changed the initial deserialization capacity for the affected structures so it no longer equals the full attacker-declared count.
For CompactHashMap and CompactHashSet, the patch changes initialization to use the smaller of the declared element count and 256. MapMakerInternalMap applies the same 256 cap to the initial capacity passed through MapMaker. The collections can still grow as real elements are read, but a declaration by itself no longer forces a multi-gigabyte eager allocation.
The patch also adds regression tests that substitute Integer.MAX_VALUE for the serialized size. The compact collections now fail with an IOException as the incomplete stream is consumed instead of immediately attempting the requested allocation. MapMakerInternalMap remains empty with a bounded initial table.
This patch difference supports a clear verification rule: the deployed artifact must contain Guava 33.7.2 or a later release that retains the bounded initialization behavior.

Explore Penligent for authorized security testing and remediation verification.
Dependency presence is not the same as exploitability
An accurate triage separates four questions:
- Is Guava present? A build, container, application server, plugin, or shaded JAR contains the library.
- Is the version affected? The deployed copy resolves to 4.0 through 33.7.1.
- Is native deserialization reachable? Untrusted or cross-trust-boundary bytes can reach ObjectInputStream or an equivalent framework path.
- Can the affected classes be resolved? The vulnerable Guava classes are available to the deserializing class loader and are not blocked by an effective serialization filter.
The first two questions establish vulnerability exposure in the software supply chain. The last two determine immediate exploitability in a specific service. Use reachability to prioritize emergency work, not to justify leaving an old dependency indefinitely.
Audit Maven projects
Start with the resolved dependency graph rather than only the pom.xml. Guava is frequently introduced transitively.
mvn -q dependency:tree -Dincludes=com.google.guava:guava
For a multi-module build, run the command at the aggregate project and in modules that produce independently deployed artifacts. Record the selected version and the dependency path that introduced it.
If dependencyManagement overrides Guava, verify that the effective POM and the packaged application agree. A source declaration of 33.7.2 is not sufficient if another build step copies an older JAR into the deployment image.
Useful evidence includes:
- the dependency-tree output;
- the effective POM or dependency-lock record;
- the final artifact checksum;
- the Guava version extracted from the packaged application;
- the production image digest.
Audit Gradle projects
Use dependencyInsight against the configuration that becomes the deployed runtime classpath:
./gradlew dependencyInsight --dependency com.google.guava:guava --configuration runtimeClasspath
Applications may have more than one relevant configuration. Server, worker, test fixture, Android, plugin, and code-generation modules can resolve different Guava variants. Check the configuration that produces each deployable process rather than assuming the root project’s result applies everywhere.
If version catalogs or dependency constraints are used, preserve the lockfile change and the resolved dependency report as remediation evidence.
Find JARs outside normal dependency graphs
Build-tool output can miss copies introduced after dependency resolution. Search application images, application-server shared libraries, plugin directories, and unpacked distributions for files such as guava-33.7.1-jre.jar or guava-32.x-android.jar.
For an ordinary JAR, the Maven metadata may disclose the version:
unzip -p guava.jar META-INF/maven/com.google.guava/guava/pom.properties
For an executable or fat JAR, first look for embedded Maven metadata:
unzip -l application.jar | grep 'com.google.guava/guava/pom.properties'
If metadata is present, extract it. If Guava was shaded and metadata was removed, class presence alone cannot identify the exact version. Use the build provenance, software bill of materials, dependency lock, or a known artifact hash. Do not infer that a shaded copy is patched because its outer application version is recent.
Also check:
- base images that provide Java libraries;
- vendor products that embed a JVM application;
- CI tools and build agents that deserialize remote job or cache data;
- desktop or agent software that accepts serialized files;
- old deployment layers retained in a container registry.
Audit native-deserialization reachability
Search source and configuration for ObjectInputStream, readObject, XMLDecoder, RMI, JMX remoting, HTTP-session persistence, message consumers, cache replication, and framework features that accept Java-serialized objects. Not every occurrence is remotely reachable, but each is a review anchor.
For each path, document:
- who can supply the bytes;
- whether the data crosses a tenant, user, network, or privilege boundary;
- whether authentication occurs before deserialization;
- whether integrity protection is cryptographically enforced;
- which class loader handles the stream;
- whether an ObjectInputFilter or equivalent allowlist is active;
- the maximum accepted object depth, array length, reference count, and byte count;
- whether the service can be restarted safely if heap exhaustion occurs.
JEP 290 serialization filters can reduce risk when they are correctly applied, but a filter is a compensating control, not a substitute for upgrading. Validate the filter on the actual deserialization path and confirm that it rejects the affected Guava classes or prevents unreasonable graph and array sizes. A global filter that is overridden by a stream-specific filter may not provide the protection assumed by a policy document.
A safe validation workflow
Do not validate production by replaying a memory-exhaustion payload. The patch and deployment can be verified without attempting to crash a JVM.
- Resolve the build dependency and confirm Guava 33.7.2 or later.
- Inspect the final JAR, WAR, EAR, container layer, or distribution that will be deployed.
- Start the application in an isolated staging environment and record the runtime classpath or loaded Guava artifact.
- Exercise normal serialization-dependent functions with benign data.
- Confirm that serialization filters and request-size controls remain active after the upgrade.
- Capture the deployed artifact digest and the image or host inventory record.
- Re-run the dependency and SBOM scan against the deployed artifact, not only the source repository.
If an application cannot upgrade immediately, isolate the native-deserialization boundary, restrict callers, enforce strict object filters and size limits, and shorten the exception window. Treat these measures as temporary risk reduction.

Explore Penligent for authorized security testing and remediation verification.
What to do when multiple Guava versions are present
Multiple copies can exist in different class loaders. The version selected by the application at runtime may differ from the version shown by a repository scanner.
Map each copy to its loading context:
- application classpath;
- application-server shared classpath;
- plugin or extension class loader;
- job runner or build-tool classpath;
- shaded application namespace;
- Android application package.
Remove obsolete duplicates where possible. If coexistence is required, prove which copy serves each deserialization path. A patched main application does not remediate an older plugin that runs its own ObjectInputStream.
Remediation evidence for auditors and incident responders
A complete closure record should answer more than “the build passed.” Include:
- affected asset and owner;
- previous and fixed Guava versions;
- direct or transitive dependency path;
- native-deserialization entry points reviewed;
- serialization filter status;
- artifact and container digests before and after remediation;
- deployment time;
- verification time and operator;
- exception records for systems that could not be upgraded;
- monitoring or restart events that might indicate earlier OutOfMemoryError activity.
Historical OutOfMemoryError events are not proof of exploitation. They are a reason to correlate memory failures with incoming serialized data, process restarts, authentication context, and network telemetry.
Final guidance
Upgrade Guava to 33.7.2 or later wherever the affected package is deployed. Then verify the runtime artifact and review native Java deserialization across trust boundaries.
The fastest useful triage is a two-axis decision: affected version و untrusted-deserialization reachability. Systems that satisfy both conditions deserve immediate remediation. Systems that appear unreachable still need the version update and a documented reason for their lower operational priority.
Explore Penligent for authorized security testing and remediation verification.

