CVE
CVE-2026-110879, CVE-2026-54512, CVE-2026-104016, CVE-2026-110747, CVE-2026-104895, CVE-2026-102554, CVE-2026-102479
CWE
CWE-502, CWE-444, CWE-190, CWE-770, CWE-789
Affected Surface
- Maven `com.fasterxml.jackson.core:jackson-databind` (`2.10.0..2.18.11`, `2.19.0..2.21.7`, `2.22.0..2.22.3`) and `tools.jackson.core:jackson-databind` (`3.0.0..3.1.7`, `3.2.0..3.2.3`) for `CVE-2026-110879` (`GHSA-m8xf-2cr7-77ph`)
- Maven `com.fasterxml.jackson.dataformat:jackson-dataformat-protobuf` and `tools.jackson.dataformat:jackson-dataformat-protobuf` (`2.6.0..2.18.11`, `2.19.0..2.21.7`, `2.22.0..2.22.3`, `3.0.0..3.1.7`, `3.2.0..3.2.3`) for `CVE-2026-104016` (`GHSA-c2rq-mcfv-jw29`) and `CVE-2026-110747` (`GHSA-fv7v-rrmh-4qcv`)
- Maven `com.fasterxml.jackson.dataformat:jackson-dataformat-smile` and `tools.jackson.dataformat:jackson-dataformat-smile` (`2.9.0..2.18.11`, `2.19.0..2.21.7`, `2.22.0..2.22.3`, `3.0.0..3.1.7`, `3.2.0..3.2.3`) for `CVE-2026-104895` (`GHSA-h3c2-2m49-r49w`)
- Maven `com.google.guava:guava` versions `4.0` through `33.7.1-jre` / `33.7.1-android` (`CVE-2026-102554` / `GHSA-xxph-c9ww-hj94`)
- Maven `io.vertx:vertx-core` versions `5.0.0` through `5.0.12`, `5.1.0` through `5.1.9`, and `5.2.0` (`CVE-2026-102479` / `GHSA-ch7p-g5pm-3gqx`), including downstream Quarkus, `apache/camel-quarkus`, and `strimzi/strimzi-kafka-bridge 0.33.0` deployments behind HTTP/1.1 reverse proxies
TL;DR
On 27 and 28 October 2026, six vulnerabilities across three core Java libraries (FasterXML Jackson, Google Guava, and Eclipse Vert.x) were published to NVD, GitHub Advisory Database, and oss-security:
jackson-databindPolymorphicTypeValidatorgeneric and array element bypass (CVE-2026-110879/GHSA-m8xf-2cr7-77ph, CVSS 9.8 Critical): An incomplete fix for June’sCVE-2026-54512(GHSA-j3rv-43j4-c7qm) leftDatabindContext._resolveAndValidateGeneric()validating generic type arguments against the outer base type rather thanObject.class, and replacing the caller’sPolymorphicTypeValidatorwithApprovedBaseTypeValidator/LaissezFaireSubTypeValidatoronce the outer container type was approved byallowIfBaseType(...). A property declared asMap<String, String>acceptedHashMap<FileSystemXmlApplicationContext, String>, invoking Spring’s one-string XML constructor during map-key discovery to reachProcessBuilder.start()RCE. Array element types in[Lpkg.Gadget;and[[Lpkg.Gadget;bypassed validation in the same way.- Eclipse Vert.x
5.xContent-XengthHTTP/1.x request smuggling (“Byte Debt”,CVE-2026-102479/GHSA-ch7p-g5pm-3gqx, CVSS v4.0 8.7 High): To avoid string allocations when interning common HTTP headers,VertxHttpRequestDecoder.isContentLength()checked bytes1..7("ontent-") and bytes9..13("ength"), completely skipping index8('L'). Any 14-byte header matchingContent-*ength(such asContent-Xength: 50) was treated by Vert.x asContent-Lengthwhile reverse proxies (Nginx, HAProxy, Envoy, Traefik, Caddy, Apache httpd, nghttpx) forwarded it as an unknown custom header. On 28 October, JFrog Security Research published a “dangling-byte” double-desync chain achieving cross-user session fixation across all seven proxies. jackson-dataformat-protobufandjackson-dataformat-smile8-to-33-byteOutOfMemoryErrorcrashes (CVE-2026-104016,CVE-2026-110747, andCVE-2026-104895, CVSS 7.5 High): InProtobufParser, checking(_inputPtr + len) <= _inputEndwith 32-bit signed integers wrapped to a negative number when a varint length was nearInteger.MAX_VALUE, bypassingStreamReadConstraintsand crashing the JVM inArrays.copyOf()on a 33-byte message (CVE-2026-104016) or an 8-bytemap<string, V>entry (CVE-2026-110747). Injackson-dataformat-smile’s reactiveNonBlockingByteArrayParser, raw-binary token0xFDomitted the(value >>> 25) != 0VInt overflow guard and allocatednew byte[len](~2 GB) from a 10-byte feed (CVE-2026-104895).- Google Guava collection deserialization
OutOfMemoryError(CVE-2026-102554/GHSA-xxph-c9ww-hj94, CVSS v4.0 8.2 High): Incom.google.guava:guava4.0through33.7.1,CompactHashMap,CompactHashSet, andMapMakerInternalMapread an unvalidated 32-bitelementCount/sizefromObjectInputStreamand eagerly allocated backing arrays for up to2^30 - 1(~1.07 billion) entries on a 72-byte serialized stream.
What to do now: Upgrade jackson-databind, jackson-dataformat-protobuf, and jackson-dataformat-smile to 2.18.12, 2.21.8, 2.22.4, 3.1.8, or 3.2.4; upgrade com.google.guava:guava to 33.7.2-jre (or 33.7.2-android); and upgrade io.vertx:vertx-core on the 5.x line to 5.1.10 or 5.2.1+ (5.2.2 is current).
Affected packages and projects
| Ecosystem | Maven coordinates | CVE / Advisory | Severity | Affected versions | Fixed versions |
|---|---|---|---|---|---|
| Maven | com.fasterxml.jackson.core:jackson-databind, tools.jackson.core:jackson-databind | CVE-2026-110879 (GHSA-m8xf-2cr7-77ph) | CVSS 9.8 Critical | 2.10.0..2.18.11, 2.19.0..2.21.7, 2.22.0..2.22.3, 3.0.0..3.1.7, 3.2.0..3.2.3 | 2.18.12, 2.21.8, 2.22.4, 3.1.8, 3.2.4 |
| Maven | com.fasterxml.jackson.dataformat:jackson-dataformat-protobuf, tools.jackson.dataformat:jackson-dataformat-protobuf | CVE-2026-104016 (GHSA-c2rq-mcfv-jw29) | CVSS 7.5 High | 2.6.0..2.18.11, 2.19.0..2.21.7, 2.22.0..2.22.3, 3.0.0..3.1.7, 3.2.0..3.2.3 | 2.18.12, 2.21.8, 2.22.4, 3.1.8, 3.2.4 |
| Maven | com.fasterxml.jackson.dataformat:jackson-dataformat-protobuf, tools.jackson.dataformat:jackson-dataformat-protobuf | CVE-2026-110747 (GHSA-fv7v-rrmh-4qcv) | CVSS 7.5 High | 2.21.6..2.21.7, 2.22.0..2.22.3, 3.1.6..3.1.7, 3.2.2..3.2.3 | 2.21.8, 2.22.4, 3.1.8, 3.2.4 |
| Maven | com.fasterxml.jackson.dataformat:jackson-dataformat-smile, tools.jackson.dataformat:jackson-dataformat-smile | CVE-2026-104895 (GHSA-h3c2-2m49-r49w) | CVSS 7.5 High | 2.9.0..2.18.11, 2.19.0..2.21.7, 2.22.0..2.22.3, 3.0.0..3.1.7, 3.2.0..3.2.3 | 2.18.12, 2.21.8, 2.22.4, 3.1.8, 3.2.4 |
| Maven | com.google.guava:guava | CVE-2026-102554 (GHSA-xxph-c9ww-hj94) | CVSS v4.0 8.2 High | 4.0 through 33.7.1-jre / 33.7.1-android | 33.7.2-jre, 33.7.2-android |
| Maven | io.vertx:vertx-core | CVE-2026-102479 (GHSA-ch7p-g5pm-3gqx) | CVSS v4.0 8.7 High | 5.0.0..5.0.12, 5.1.0..5.1.9, 5.2.0 | 5.1.10, 5.2.1 (5.2.2 current) |
Technical analysis
1. CVE-2026-110879: how generic type arguments and array elements bypassed PolymorphicTypeValidator in jackson-databind
When jackson-databind patched CVE-2026-54512 (GHSA-j3rv-43j4-c7qm), it added _validateTypeParameter() inside DatabindContext._resolveAndValidateGeneric() so that a type ID like java.util.ArrayList<EvilGadget> would have its type arguments checked.
However, as Adam Korcz and François Martin reported, three flaws in _resolveAndValidateGeneric() and _validateTypeParameter() allowed attacker-chosen classes inside generic parameters or array descriptors ([L...;, [[L...;) to bypass validation anyway:
- Validating type arguments against the outer
baseTypeinstead ofObject.class:_validateTypeParameter(baseType, subType.containedType(i), ptv, config)passed the outer property’sbaseTypetoptv.validateSubClassName(config, baseType, rawName)andptv.validateSubType(config, baseType, param). Under Jackson’s defaultDefaultBaseTypeLimitingValidator(used with@JsonTypeInfo(use = Id.CLASS)without a custom validator),validateBaseType()andvalidateSubType()assumed the subtype relationship had already been checked, so any class nested inside a generic argument was approved even though selecting that same class directly as the outer type ID failed with"Not a subtype". allowIfBaseType(...)substituted a permissive validator for embedded arguments: When aBasicPolymorphicTypeValidatorrule approved the outer container viaallowIfBaseType(...)(for example permittingMap), Jackson wrapped or substituted the validator so that embedded generic arguments were no longer checked against the configured subtype rules. Declaring a field asMap<String, String>allowed the JSON payload to specify"@class": "java.util.HashMap<org.springframework.context.support.FileSystemXmlApplicationContext, java.lang.String>". During map-key deserialization, Jackson passed the attacker-controlled JSON property name toFileSystemXmlApplicationContext(String), loading an XML bean definition and executingProcessBuilder.start().- Multi-dimensional and
Serializable[]array descriptors (PR #6289): When an array type ID such as[[Lcom.example.Gadget;was validated against a rule likeallowIfSubType(Object[][].class)orallowIfSubType(Serializable[].class),_isSpecificallyApprovedArrayType()only probedObject[](1D), concluded the rule was a narrow array approval, and skipped validating the element typeGadget.
PR #6287 and PR #6289 fix all three paths in DatabindContext.java by unwrapping ApprovedBaseTypeValidator back to the caller’s configured PolymorphicTypeValidator, validating every class named in a type parameter or array element as if it were a direct type ID for base type Object.class, and probing array rules across Object, Serializable, and Cloneable at the array’s exact dimension depth:
--- a/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java
@@ -288,14 +291,13 @@ private JavaType _resolveAndValidateGeneric(JavaType baseType, String subClass,
- for (int i = 0, n = subType.containedTypeCount(); i < n; ++i) {
- _validateTypeParameter(baseType, subType.containedType(i), ptv, config);
- }
- if (subType.isArrayType()) {
- _validateTypeParameter(baseType, subType.getContentType(), ptv, config);
+ // [CVE-2026-110879]: ... and validated with the configured validator (not one
+ // that approves all subtypes of the base type) and as if named as a direct
+ // type id for base type `Object` -- type parameter may bind to anything.
+ if (ptv instanceof ApprovedBaseTypeValidator) {
+ ptv = ((ApprovedBaseTypeValidator) ptv).getTypeParameterValidator();
}
+ _validateTypeParameters(baseType, subClass, subType, ptv, config);
2. CVE-2026-102479: Eclipse Vert.x 5.x Content-Xength header canonicalization and the “dangling-byte” smuggling chain
In Eclipse Vert.x 5.0.0 through 5.0.12, 5.1.0 through 5.1.9, and 5.2.0, VertxHttpRequestDecoder.splitHeaderName() optimized HTTP/1.x header parsing by packing header name bytes into 64-bit long and 32-bit int values and comparing them against precomputed constants before allocating a new AsciiString.
For 12-byte (Content-Type) and 14-byte (Content-Length) headers starting with 'C' or 'c', isContentType() and isContentLength() packed bytes 1..7 ("ontent-") into a long and packed the trailing bytes ("ype" at offsets 9..11 or "ength" at offsets 9..13) into an int, leaving byte offset 8 ('T' or 'L') completely unchecked:
--- a/vertx-core/src/main/java/io/vertx/core/http/impl/http1/VertxHttpRequestDecoder.java
+++ b/vertx-core/src/main/java/io/vertx/core/http/impl/http1/VertxHttpRequestDecoder.java
@@ -90,12 +110,22 @@ protected AsciiString splitHeaderName(byte[] sb, int start, int length) {
} else if (length == 12) {
- if (isContentType(sb, start)) {
- return firstChar == 'C' ? _Content_Type : HttpHeaderNames.CONTENT_TYPE;
+ if (mightBeContentType(sb, start)) {
+ byte maybeT = sb[start + 8];
+ if (firstChar == 'C' && maybeT == 'T') {
+ return _Content_Type;
+ } else if (firstChar == 'c' && maybeT == 't') {
+ return HttpHeaderNames.CONTENT_TYPE;
+ }
}
} else if (length == 14) {
- if (isContentLength(sb, start)) {
- return firstChar == 'C' ? _Content_Length : HttpHeaderNames.CONTENT_LENGTH;
+ if (mightBeContentLength(sb, start)) {
+ byte maybeL = sb[start + 8];
+ if (firstChar == 'C' && maybeL == 'L') {
+ return _Content_Length;
+ } else if (firstChar == 'c' && maybeL == 'l') {
+ return HttpHeaderNames.CONTENT_LENGTH;
+ }
}
}
As JFrog Security Research detailed on 28 October (Byte Debt), sending both Content-Length and Content-Xength in the same request is rejected by Netty’s duplicate Content-Length check (400 Bad Request). Instead, an attacker sends a single request A carrying Content-Xength: <N> and no body to an endpoint that does not read the request body:
- The reverse proxy (Nginx, HAProxy, Envoy, Traefik, Caddy, Apache httpd, or nghttpx) treats
Content-Xengthas a harmless custom header, forwards requestAwith no body, receives Vert.x’s immediate HTTP response, and returns the backend TCP connection to its keep-alive pool while Vert.x is still waiting to read<N>body bytes on that socket (“byte debt”). - On a second request
Bthat reuses the pooled connection, the attacker sends a body containing two spliced HTTP requestsCandD, whereD(for examplePOST /loginwith the attacker’s credentials) declares a body length 1 byte longer than the bytes actually sent. - Vert.x consumes
B’s headers asA’s leftover body, replies toC(which the proxy returns as the response toB), and pauses while waiting for the single “dangling byte” ofD. BecauseDhas not emitted a response yet, the proxy’s idle-socket check sees an empty read buffer and returns the poisoned connection to the pool. - When the next victim user sends a request on that connection, the very first byte of their HTTP request (
GinGET /...) satisfiesD’s 1-byte debt, and Vert.x immediately returns the attacker’sPOST /login303 Set-Cookieresponse to the victim’s browser.
Commit 317c778d7f (shipped in 5.1.10 and 5.2.1) checks sb[start + 8] explicitly for both Content-Type and Content-Length.
3. CVE-2026-104016, CVE-2026-110747, and CVE-2026-104895: Jackson Protobuf and Smile OutOfMemoryError crashes
Three High-severity advisories in FasterXML/jackson-dataformats-binary allow tiny payloads (8 to 33 bytes) to crash the JVM or throw uncaught NegativeArraySizeException before StreamReadConstraints can intervene:
- Protobuf signed-int
_inputPtr + lenoverflow (CVE-2026-104016andCVE-2026-110747, commit671db43487and commita4d05bd166): InProtobufParser.java,nextTextValue(),getText(), and_readStringKey()(used formap<string, V>keys) checked whether the entire string was already buffered in memory using 32-bit signed arithmetic:
When an attacker supplied a 5-byte varint decoding to- if ((_inputPtr + len) <= _inputEnd) { + // Compare against remaining input: `_inputPtr + len` may overflow + if (len <= (_inputEnd - _inputPtr)) { return _finishShortText(len); }Integer.MAX_VALUE(0x7fffffff) while_inputPtr >= 1,_inputPtr + lenwrapped to a negativeint, satisfying<= _inputEndand calling_finishShortText(Integer.MAX_VALUE)->TextBuffer.expandCurrentSegment(len)->Arrays.copyOf(curr, len), which immediately threwOutOfMemoryError: Requested array size exceeds VM limit. - Smile async
NonBlockingByteArrayParserraw-binary eager allocation (CVE-2026-104895, commit60e58bbb24): On a Smile raw-binary token (0xFD), the blockingSmileParser._readUnsignedVInt()guarded against 32-bit shift overflow withif ((value >>> 25) != 0), but the reactive/non-blockingNonBlockingByteArrayParser._decodeVInt()omitted the check and passed the decodedlendirectly into_binaryValue = new byte[len]inside_startRawBinary()before any payload bytes arrived. A 10-byte Smile frame forced an immediate ~2 GBbyte[]allocation (orNegativeArraySizeExceptionon overflow) in Spring WebFlux, Vert.x, or Micronaut pipelines.
4. CVE-2026-102554: Google Guava CompactHashMap, CompactHashSet, and MapMakerInternalMap deserialization OOM
In com.google.guava:guava 4.0 through 33.7.1, CompactHashMap.readObject(), CompactHashSet.readObject(), and MapMakerInternalMap.readMapMaker() read a 32-bit elementCount or size integer from ObjectInputStream and passed it directly into init(elementCount) or .initialCapacity(size).
Because init(elementCount) only clamped the count to CompactHashing.MAX_SIZE (2^30 - 1, or ~1.07 billion elements), a 72-byte Java serialization stream declaring elementCount = 1_073_741_823 followed by a single element caused the first put() / add() call to allocate new int[2^30], new Object[2^30], and new Object[2^30], crashing the JVM with OutOfMemoryError. Commit b931fe9d6d (released in Guava 33.7.2-jre and 33.7.2-android) caps the initial capacity allocated during deserialization at 256 (init(min(elementCount, 256))), allowing larger collections to grow naturally as real elements are read from the stream:
--- a/guava/src/com/google/common/collect/CompactHashMap.java
+++ b/guava/src/com/google/common/collect/CompactHashMap.java
@@ -1129,7 +1129,7 @@ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFo
if (elementCount < 0) {
throw new InvalidObjectException("Invalid size: " + elementCount);
}
- init(elementCount);
+ init(min(elementCount, 256));
for (int i = 0; i < elementCount; i++) {
Detection and remediation
# 1. Check Maven and Gradle manifests and lockfiles for vulnerable Jackson, Guava, and Vert.x versions
rg -n '(jackson-databind|jackson-bom|jackson-dataformat-protobuf|jackson-dataformat-smile|com\.google\.guava:guava|io\.vertx:vertx-core)' \
pom.xml '**/pom.xml' build.gradle* '**/build.gradle*' gradle.lockfile '**/gradle.lockfile' gradle/libs.versions.toml 2>/dev/null
# 2. Audit Java/Kotlin codebases for class-name polymorphic deserialization and non-blocking Smile parsers
rg -n 'activateDefaultTyping|enableDefaultTyping|JsonTypeInfo\.Id\.(MINIMAL_)?CLASS|createNonBlockingByteArrayParser' \
src/ '**/src/' 2>/dev/null
- Upgrade Jackson (
2.18.12,2.21.8,2.22.4,3.1.8, or3.2.4): Bumpjackson-bomor individualjackson-databind,jackson-dataformat-protobuf, andjackson-dataformat-smilecoordinates. Note that after upgrading to2.18.12+/2.22.4+/3.2.4+, anyPolymorphicTypeValidatorconfiguration that previously relied on an approved outer generic container (List,Map) or array type (Object[][],Serializable[]) to implicitly allow unlisted type arguments or element classes will now reject those payloads unless the element classes themselves are allowlisted. - Upgrade Eclipse Vert.x (
5.1.10or5.2.1+): Any service on the Vert.x5.0.x,5.1.x < 5.1.10, or5.2.0branch (including Quarkus,camel-quarkus, or Strimzi Kafka Bridge0.33.0containers) should upgradeio.vertx:vertx-coreto5.1.10or5.2.1+(5.2.2is current). If you cannot upgrade immediately, configure your front-end reverse proxy or WAF to drop requests containing any header matching^Content-[^Ll]ength$or^Content-[^Tt]ype$(case-insensitive). - Upgrade Google Guava (
33.7.2-jre/33.7.2-android): Upgradecom.google.guava:guavato33.7.2-jre(or33.7.2-android) in any application that deserializes JavaObjectInputStreamdata, and configure anObjectInputFilter(jdk.serialFilter) that boundsmaxarray.
Timeline
- 2026-09-23: Julien Viet commits
317c778d7ftoeclipse-vertx/vert.xto verify byte offset8inVertxHttpRequestDecoder.splitHeaderName(). - 2026-09-29: Google commits
b931fe9d6dand releasescom.google.guava:guava33.7.2-jreand33.7.2-android(GHSA-xxph-c9ww-hj94). - 2026-09-30 to 2026-10-02: FasterXML merges commits
671db43487,a4d05bd166, and60e58bbb24injackson-dataformats-binary. - 2026-10-15 to 2026-10-18: FasterXML merges PRs
#6287and#6289injackson-databindand publishes2.18.12,2.21.8,2.22.4,3.1.8, and3.2.4acrossjackson-databindandjackson-dataformats-binaryto Maven Central. - 2026-10-27 to 2026-10-28: GitHub Advisory Database and NVD publish
CVE-2026-102554,CVE-2026-104016,CVE-2026-104895,CVE-2026-110747, andCVE-2026-110879, while JFrog Security Research andoss-security(2026/10/28/19) publish the Byte Debt session-fixation analysis for Eclipse Vert.xCVE-2026-102479.
From research to remediation
Check whether this pattern exists in your codebase
Turn this research into a remediation workflow. Scan dependencies and package manifests for similar supply-chain risk, then prioritize fixes with reachability context.
References
- Jackson Databind advisory GHSA-m8xf-2cr7-77ph and PRs #6287 / #6289 (CVE-2026-110879: PolymorphicTypeValidator generic and array bypass)
- FasterXML/jackson-databind PR #6287: validate generic type arguments with the configured validator
- FasterXML/jackson-databind PR #6289: validate element types of arrays approved by depth-wide rules
- Jackson Dataformats Binary advisories GHSA-c2rq-mcfv-jw29 (CVE-2026-104016), GHSA-fv7v-rrmh-4qcv (CVE-2026-110747), and GHSA-h3c2-2m49-r49w (CVE-2026-104895)
- Google Guava advisory GHSA-xxph-c9ww-hj94 and commit b931fe9d6d (CVE-2026-102554: CompactHashMap/Set and MapMakerInternalMap deserialization OOM)
- google/guava commit b931fe9d6d: cap initial deserialization capacity at 256
- Eclipse Vert.x advisory GHSA-ch7p-g5pm-3gqx and commit 317c778d7f (CVE-2026-102479: HTTP/1.x canonicalized header request smuggling)
- JFrog Security Research (28 October 2026): Byte Debt (CVE-2026-102479), from an HTTP header typo to cross-user session fixation
- oss-security (28 October 2026): CVE-2026-102479 Request smuggling in Eclipse Vert.x HTTP/1.x decoder