CVE-2026-83557 · GHSA-gx83-3vf8-gh7j
jackson-databind: Comparable missing from DefaultBaseTypeLimitingValidator's unsafe base types (incomplete PolymorphicTypeValidator denylist)
- Risk score
- 49/100
- CVSS
- 5.6 v3.1
- Exploit chance (30 days)
- 0.7%
- Published
- 28 Sep 2026
Open in the live forecast Today's forecast
What to know
- What it is
- DefaultBaseTypeLimitingValidator — the PolymorphicTypeValidator used automatically whenever @JsonTypeInfo is applied without an explicitly configured custom validator — denies polymorphic resolution only for nine specific "unsafe base types" (Object, Serializable, Closeable, AutoCloseable, Cloneable, Runnable, java.ut…
- Affected
- tools.jackson.core:jackson-databind (maven) >= 3.0.0, < 3.1.6; tools.jackson.core:jackson-databind (maven) >= 3.2.0, < 3.2.2; com.fasterxml.jackson.core:jackson-databind (maven) >= 2.11.0, < 2.18.10; com.fasterxml.jackson.core:jackson-databind (maven) >= 2.19.0, < 2.21.6
- Fix
- Upgrade tools.jackson.core:jackson-databind to 3.1.6 or 3.2.2; com.fasterxml.jackson.core:jackson-databind to 2.18.10 or 2.21.6 or 2.22.2 (whichever matches your release line) or later.
- Exploitation
- No known exploitation
Why it is Yellow
- CVSS 5.6 medium
- On your watchlist: Maven
Affected packages
| Package | Ecosystem | Vulnerable | Fixed in |
|---|---|---|---|
| tools.jackson.core:jackson-databind | maven | >= 3.0.0, < 3.1.6 | 3.1.6 |
| tools.jackson.core:jackson-databind | maven | >= 3.2.0, < 3.2.2 | 3.2.2 |
| com.fasterxml.jackson.core:jackson-databind | maven | >= 2.11.0, < 2.18.10 | 2.18.10 |
| com.fasterxml.jackson.core:jackson-databind | maven | >= 2.19.0, < 2.21.6 | 2.21.6 |
| com.fasterxml.jackson.core:jackson-databind | maven | >= 2.22.0, < 2.22.2 | 2.22.2 |
References
- https://github.com/advisories/GHSA-gx83-3vf8-gh7j
- https://github.com/FasterXML/jackson-databind/security/advisories/GHSA-gx83-3vf8-gh7j
- https://nvd.nist.gov/vuln/detail/CVE-2026-83557
- https://github.com/FasterXML/jackson-databind/issues/6156
- https://github.com/FasterXML/jackson-databind/pull/6155
- https://github.com/FasterXML/jackson-databind/commit/eb3b7fc0f9c0d27f471550ac3316b17d1987388f
- https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-2.18.10
- https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-2.21.6
- https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-2.22.2
- https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-3.1.6
Original description
### Summary `DefaultBaseTypeLimitingValidator` — the `PolymorphicTypeValidator` used automatically whenever `@JsonTypeInfo` is applied without an explicitly configured custom validator — denies polymorphic resolution only for nine specific "unsafe base types" (`Object`, `Serializable`, `Closeable`, `AutoCloseable`, `Cloneable`, `Runnable`, `java.util.logging.Handler`, `javax.naming.Referenceable`, `javax.sql.DataSource`). Its `isSafeSubType()` returns `true` unconditionally for every other base type. `java.lang.Comparable` is not in that list, despite being implemented by a very large fraction of JDK and application classes — comparable in breadth to `Serializable`, which is denylisted for exactly that reason. An application with an `@JsonTypeInfo`-annotated `Comparable`-typed property, and no custom validator configured, will accept a type identifier for essentially any class implementing `Comparable`. ### Details **Affected file:** `src/main/java/tools/jackson/databind/jsontype/DefaultBaseTypeLimitingValidator.java` ```java private final static class UnsafeBaseTypes { private final Set<String> UNSAFE = new HashSet<>(); { UNSAFE.add(Object.class.getName()); UNSAFE.add(java.io.Closeable.class.getName()); UNSAFE.add(java.io.Serializable.class.getName()); UNSAFE.add(AutoCloseable.class.getName()); UNSAFE.add(Cloneable.class.getName()); UNSAFE.add(Runnable.class.getName()); // [databind#5014] UNSAFE.add("java.util.logging.Handler"); UNSAFE.add("javax.naming.Referenceable"); UNSAFE.add("javax.sql.DataSource"); // java.lang.Comparable is NOT present here } } protected boolean isSafeSubType(DatabindContext ctxt, JavaType baseType, JavaType subType) { return true; // unconditional for every base type not in UNSAFE } ``` The class's own JavaDoc acknowledges the design (*"Note that when using potentially unsafe base type like `java.lang.Object` a custom implementation... is needed"*), so the trade-off of leaving broad base types unrestricted is intentional. The gap is that `Comparable` has the same breadth of implementers as the types this class *does* restrict, and its absence looks like an oversight rather than a deliberate choice — consistent with the ongoing, incremental nature of this list (`Runnable` was added recently for issue #5014). This is specific to the **default, unconfigured validator** reached via bare `@JsonTypeInfo` usage. Global "Default Typing" via `activateDefaultTyping()` is **not** affected, because that method structurally requires an explicit `PolymorphicTypeValidator` argument — a correctly-configured `BasicPolymorphicTypeValidator` rejects the same payload under `activateDefaultTyping()`. ### PoC Built entirely from source (jackson-databind + jackson-core + jackson-annotations, `javac`, OpenJDK 21, no third-party gadget libraries, no network access): **1. Sanity check (benign class, confirms the mechanism fires):** ```java static class SafeThing implements Comparable<SafeThing> { public String name; public SafeThing() {} public int compareTo(SafeThing o) { return 0; } } static class Holder { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) public Comparable<?> value; } ObjectMapper mapper = JsonMapper.builder().build(); // no custom PTV String json = "{\"value\":{\"@class\":\"...SafeThing\",\"name\":\"hello\"}}"; Holder h = mapper.readValue(json, Holder.class); // RESULT: ACCEPTED, class=...SafeThing ``` **2. Real JDK class substitution:** ```java String json = "{\"value\":[\"java.io.File\",\"/etc/passwd\"]}"; Holder h = mapper.readValue(json, Holder.class); // RESULT: ACCEPTED, class=java.io.File value=/etc/passwd ``` **3. Negative control — Default Typing with an explicit custom PTV:** ```java PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder() .allowIfSubType("PtvGapTest4").build(); ObjectMapper mapper = JsonMapper.builder() .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL).build(); // same java.io.File payload // RESULT: REJECTED - InvalidTypeIdException: "...denied resolution" ``` **Observed output:** $ java -cp .:build/classes PtvGapTest3 Trying: {"value":["java.io.File","/etc/passwd"]} ACCEPTED, class=java.io.File value=/etc/passwd $ java -cp .:build/classes PtvGapTest4 Trying malicious substitution: ["PtvGapTest4$Holder",{"value":["java.io.File","/etc/passwd"]}] REJECTED - InvalidTypeIdException: Could not resolve type id 'java.io.File' as a subtype of java.lang.Comparable: Configured PolymorphicTypeValidator denied resolution ### Impact Any application declaring an `@JsonTypeInfo`-annotated property or class with `Comparable` as its base type, without a separately configured restrictive `PolymorphicTypeValidator`, will accept a type identifier for essentially any class implementing `Comparable`. Concrete impact is demonstrated via `java.io.File`: an attacker can cause construction of a `File` object for an arbitrary, attacker-chosen path. On its own this is a controlled-object-instantiation primitive; if the application later calls path-sensitive or mutating methods on the received value, this becomes a path-traversal-adjacent primitive. **Suggested remediation:** 1. Add `java.lang.Comparable` to `UnsafeBaseTypes.UNSAFE`. 2. Audit other broad JDK interfaces (`java.lang.Iterable`, `java.util.EventListener`) for the same gap. 3. Consider a narrower default for `isSafeSubType()` for base types outside the fixed denylist, rather than unconditional `true`.
Last activity 28 Sep 2026. Patch Forecast updates every hour.