رأس القلم

CVE-2026-54512, Jackson PTV Bypass Through Generic Type Parameters

CVE-2026-54512 is a Jackson vulnerability that matters precisely because it can affect teams that thought they were using the safer path. The issue is not that every Java service using Jackson is instantly exploitable. The issue is narrower and more uncomfortable: when polymorphic typing is enabled, and a type identifier contains generic parameters, vulnerable jackson-databind versions can validate only the raw outer container type against the configured PolymorphicTypeValidator, then resolve and instantiate nested type arguments that were never checked against that validator. NVD describes the vulnerable path in DatabindContext._resolveAndValidateGeneric(), and GitHub’s advisory states that this can bypass an explicitly configured PTV allowlist.(NVD)

That makes CVE-2026-54512 different from a sloppy “Jackson RCE” headline. A vulnerable dependency is not enough by itself. Real exposure depends on whether the application accepts untrusted JSON, enables polymorphic deserialization, lets an attacker influence a class-name type id, relies on PTV rules for safety, and has a classpath where the smuggled type can do something security-relevant. The official CVSS 3.1 score from the CNA is 8.1 High, with network attack vector, high attack complexity, no privileges required, no user interaction, unchanged scope, and high confidentiality, integrity, and availability impact. NVD currently shows that NIST has not supplied its own CVSS score, but it displays the GitHub CNA score and vector.(NVD)

CVE-2026-54512 at a glance

Areaالتفاصيل
مكافحة التطرف العنيفCVE-2026-54512
المكوّنFasterXML jackson-databind
Primary package, Jackson 2.xcom.fasterxml.jackson.core:jackson-databind
Primary package, Jackson 3.xtools.jackson.core:jackson-databind for 3.x package coordinates listed by GitHub
WeaknessesCWE-184, Incomplete List of Disallowed Inputs, and CWE-502, Deserialization of Untrusted Data
Core bugPTV validation checks the raw container type before <, but not the nested generic type arguments
Example patternAn allowlisted container such as java.util.ArrayList wraps a denied type as a generic parameter
الإصدارات المتأثرة>= 2.10.0, <= 2.18.7, >= 2.19.0, <= 2.21.3و >= 3.0.0, <= 3.1.3 لـ com.fasterxml.jackson.core:jackson-databind; GitHub also lists tools.jackson.core:jackson-databind >= 3.0.0, <= 3.1.3
Patched versions2.18.8, 2.21.4و 3.1.4
CVSSGitHub CNA score 8.1 High, CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
First actionUpgrade jackson-databind, then prove whether untrusted JSON can reach polymorphic type ids in your runtime paths

GitHub’s advisory is the most useful starting point for package ranges and patched versions. It lists the affected com.fasterxml.jackson.core:jackson-databind ranges as >= 2.10.0, <= 2.18.7, >= 2.19.0, <= 2.21.3و >= 3.0.0, <= 3.1.3, with patched versions 2.18.8, 2.21.4و 3.1.4. It also lists tools.jackson.core:jackson-databind 3.x through 3.1.3 as affected, fixed in 3.1.4.(جيثب)

The fix also appears in the official Jackson 2.21.4 release notes. The release page says Jackson 2.21.4 was released on May 28, 2026, and its Databind section includes PolymorphicTypeValidator needs to validate generic type parameters too [CVE-2026-54512]. The same release line also includes several other Jackson security fixes, which is why teams should avoid treating this as a one-off dependency bump without checking the broader Jackson patch wave.(جيثب)

Why the risk is easy to misread

Jackson is everywhere in Java services, especially Spring-based applications, API gateways, internal platforms, stream processors, SDKs, and enterprise products. That does not mean every service with jackson-databind is exposed to CVE-2026-54512. The exposure begins when polymorphic type handling is enabled across a trust boundary.

Jackson’s own documentation defines polymorphic type handling as adding enough type information so the deserializer can instantiate the appropriate subtype of a value. That feature is useful when the declared Java type is a superclass, interface, abstract type, or الكائن, but the runtime value needs to become a concrete subtype during deserialization.(جيثب)

The dangerous version of that pattern appears when the type id is a Java class name and the attacker can influence it. Jackson’s polymorphic deserialization documentation explicitly warns that enabling global type information with class names while accepting content from untrusted sources can expose a security hole, because an attacker may specify a class available through the class loader that has methods or fields with dangerous side effects.(جيثب)

Snyk’s older Jackson deserialization write-up makes a related operational point that is still important for CVE-2026-54512: Jackson’s ObjectMapper is not automatically unsafe by default, and many historical Jackson deserialization vulnerabilities depend on default typing being explicitly enabled. The same article warns that if default typing is enabled globally and a field of type الكائن is fed with untrusted input, a class available on the classpath may be deserialized and used as part of a gadget path.(Snyk)

CVE-2026-54512 lands in the gap between “we know polymorphic class-name typing can be dangerous” and “we configured a PTV allowlist, so we are safe.” The bug is not a missing blocklist entry for one more gadget class. It is a validation bypass in the generic type resolution path. A team can use the recommended-looking control, approve only a container class, and still have a nested type argument slip through on vulnerable versions.

The security role of PolymorphicTypeValidator

PolymorphicTypeValidator exists because class-name-based polymorphic deserialization needs a gatekeeper. Its Javadoc describes it as the interface for validation of class-name-based subtypes used with polymorphic deserialization, including default typing and explicit @JsonTypeInfo when Java class names are used as type identifiers. The same Javadoc says its main purpose is to allow pluggable allowlists to avoid security problems caused by unlimited class names.(FasterXML)

The intended flow is roughly this:

  1. Jackson sees a polymorphic property or root value.
  2. Jackson asks whether the base type itself can be accepted or denied.
  3. If that does not settle the question, Jackson sees a class-name type id and asks the validator whether that subtype name is allowed.
  4. If still necessary, Jackson resolves the class and asks about the resolved subtype.
  5. If the validator denies or cannot approve the type, deserialization should fail.

That model is only useful if the type being instantiated is the type that was actually validated. CVE-2026-54512 breaks that expectation in a specific path. The outer container type gets checked. The nested generic parameter does not. The result is not a failure of every PTV design; it is a failure to apply the validator recursively to the full type structure represented by the type id.

A simplified unsafe mental model looks like this:

Incoming type id:
  java.util.ArrayList<com.example.DeniedType>

Vulnerable validation path:
  Validate only:
    java.util.ArrayList

Then parse full canonical type:
  java.util.ArrayList<com.example.DeniedType>

Security problem:
  com.example.DeniedType was part of the actual type structure,
  but it was not put through the same PTV decision.

That distinction matters in code review. If reviewers only ask, “Is there a PTV?” they may miss the vulnerability. The better question is, “Can attacker-controlled type ids express a nested class that the validator did not actually approve?”

Root cause, raw container validation instead of full generic validation

How the Generic Type Parameter Bypasses PTV Validation

The official advisory describes the vulnerable behavior directly. When polymorphic typing is enabled and the type id string contains <, DatabindContext._resolveAndValidateGeneric() validates only the raw container class name, which is the substring before <, against the configured PTV. If that container is approved, Jackson parses the full canonical type string through TypeFactory.constructFromCanonical() and returns the parameterized type without validating nested type arguments against the PTV. The nested arguments are then resolved, instantiated, and populated as beans during deserialization.(جيثب)

NVD’s description says the same thing in operational terms: an attacker who controls the type id can place a denied class as a generic type parameter of an allowed container, such as a denied type inside java.util.ArrayList when only java.util.ArrayList is allowlisted. NVD further states that the nested class can be loaded through Class.forName(name, true, loader), instantiated, and populated with attacker-controlled JSON properties.(NVD)

The important point is not the literal example class name. The important point is the trust boundary. The allowlist decision was made on a different type than the one that later mattered.

The vulnerable path can be described in five steps:

الخطوةWhat happensما أهمية ذلك
1A JSON payload contains a polymorphic type idThe attacker-controlled type id is the entry point
2The type id includes a generic parameterThe string contains <, creating a full canonical generic type
3The raw container class is extractedOnly the substring before < is checked
4The container passes PTVThe outer shell is accepted
5Nested type arguments are resolved and populatedThe denied inner type can become the object that receives attacker-controlled properties

This is why CVE-2026-54512 is not just another gadget-chain story. Gadget risk is the impact amplifier. The core bug is earlier: a validator meant to constrain concrete class instantiation did not validate every concrete class expressed in the type id.

Affected versions and patch path

The fastest safe answer is to upgrade to a fixed jackson-databind version. For Jackson 2.18.x, move to 2.18.8 or later on that maintained line. For Jackson 2.19 through 2.21, move to 2.21.4 or later on that line. For Jackson 3.x, move to 3.1.4 or later. GitHub’s advisory lists those fixed versions, and the Jackson 2.21.4 release notes include the CVE-2026-54512 fix in the Databind section.(جيثب)

A practical remediation table looks like this:

Current lineAffected rangeMinimum fixed versionPractical note
Jackson 2.18.x>= 2.10.0, <= 2.18.72.18.8Use this when pinned to the 2.18 maintenance line
Jackson 2.19 to 2.21>= 2.19.0, <= 2.21.32.21.4Prefer a framework-managed BOM update where possible
Jackson 3.x, com.fasterxml coordinate>= 3.0.0, <= 3.1.33.1.4Confirm actual artifact coordinates in the build
Jackson 3.x, tools.jackson coordinate>= 3.0.0, <= 3.1.33.1.4GitHub lists this package separately for 3.x

Do not stop at the source tree. Java applications frequently carry Jackson through transitive dependencies, plugin packages, platform SDKs, vendor clients, test utilities that leak into runtime, and shaded JARs. A pull request that changes pom.xml أو build.gradle is not closure. Closure means the deployed artifact contains a fixed jackson-databind, the running container or VM uses that artifact, and the service behavior has been regression-tested.

For Maven projects, start with:

mvn -q dependency:tree -Dincludes=com.fasterxml.jackson.core:jackson-databind
mvn -q dependency:tree -Dincludes=tools.jackson.core:jackson-databind

For Gradle projects, use the runtime classpath rather than only the compile classpath:

./gradlew dependencies --configuration runtimeClasspath | grep -i jackson-databind
./gradlew dependencyInsight --dependency jackson-databind --configuration runtimeClasspath

For packaged artifacts, inspect what actually shipped:

jar tf build/libs/app.jar | grep -i 'jackson-databind'
find . -name '*.jar' -print | xargs -I{} sh -c 'jar tf "{}" 2>/dev/null | grep -qi jackson-databind && echo "{}"'

These commands do not prove exploitability. They prove inventory. That is the first layer. The second layer is reachability: whether untrusted input can reach the vulnerable polymorphic type-resolution path.

Exploitability depends on more than the dependency

The advisory’s CVSS vector has high attack complexity for a reason. A service with the vulnerable version is not automatically exploitable. CVE-2026-54512 becomes dangerous when several conditions line up.

The realistic condition set looks like this:

ConditionRequired for meaningful exposureHow to check
Vulnerable jackson-databind versionنعمDependency tree, SBOM, image scan, runtime artifact inspection
Polymorphic typing enabledUsually yesالبحث عن activateDefaultTyping, setDefaultTyping, @JsonTypeInfo, custom TypeResolverBuilder
Java class-name type ids acceptedImportantابحث عن JsonTypeInfo.Id.CLASS, default typing, wrapper array patterns
Attacker can influence the type idالحرجةTrace endpoint body, queue message, cache value, webhook, plugin config, imported JSON
PTV allowlist is relied onCritical to this CVESearch BasicPolymorphicTypeValidator, custom PTVs, allowIfSubType rules
Approved container type existsOftenLook for allowlists that approve ArrayList, HashMap, collection packages, or broad package prefixes
Denied class can be nested as a type parameterCase-specificReview generic base types and assignability
Classpath contains a useful side-effect classNeeded for RCE-like impactReview dependencies, gadget exposure, constructor and setter side effects
Endpoint is reachable by low-trust usersDrives priorityCheck internet exposure, auth requirements, tenant boundaries, internal trust assumptions

GitHub’s advisory states that the impact includes bypass of the PTV allowlist, arbitrary class instantiation of a type assignable to the container’s element or parameter position, and potential unauthenticated remote code execution when a class with exploitable side effects is present on the classpath. It specifically frames applications that accept untrusted JSON and rely on a configured PTV as affected.(جيثب)

The phrase “potential remote code execution” should be handled carefully. It is not safe to tell leadership “all Jackson services are RCE.” It is also not safe to close the issue because no one has shown a production-specific exploit. The right statement is tighter: vulnerable versions can allow a PTV allowlist bypass through generic type parameters, and the worst-case impact depends on reachable polymorphic deserialization plus available side-effect classes.

Where the attack surface usually hides

Security teams often search only HTTP controllers and miss other JSON boundaries. CVE-2026-54512 is about deserialization, not about REST specifically. Any path that deserializes attacker-influenced JSON with polymorphic type ids deserves review.

Common places to check include:

Surfaceما أهمية ذلكReview focus
Public REST APIsMost obvious untrusted JSON boundaryControllers accepting الكائن, abstract types, interface fields, polymorphic DTOs
WebhooksThird parties send structured JSONSignature verification does not make unsafe deserialization safe
Message queuesInternal topics often carry semi-trusted JSONProducer trust, tenant separation, dead-letter replay paths
Workflow enginesRules and task payloads often need dynamic typesPlugin boundaries and user-authored workflow JSON
Cache/session storesSerialized values may cross trust boundariesSession fixation, cache poisoning, shared tenant keys
Admin import/export“Admin-only” does not mean safeLower-privileged admins, compromised admin accounts, support uploads
SDK endpointsVendor clients may pass through user fieldsGenerated models with الكائن or polymorphic fields
AI and automation platformsTools often process user-supplied task JSONConnector config, tool arguments, agent memory, imported runs

The internal-message case is especially easy to underestimate. A queue might be “internal,” but if a low-privileged tenant can create an object that later becomes a queue message, the queue consumer may be deserializing untrusted data. The same is true for support import tools, marketplace integrations, plugin manifests, and automation platforms where users can upload JSON configuration.

Safe PoC demonstration, local only, no gadget chain

The following PoC is intentionally limited. It is not a weaponized exploit. It does not execute commands, open sockets, read files, write files, bypass authentication, scan targets, or use a real gadget class. It shows one defensive idea only: on an affected jackson-databind version, a type id that names an allowlisted outer container can carry a nested local class that the PTV did not allow directly. The toy class only records that Jackson instantiated it and called a setter. Run it only in a local throwaway project that you own.

The demonstration mirrors the vulnerability shape described by the public advisory, but uses a harmless class name and a local assertion instead of any exploit chain. On patched versions, the same test should fail before the nested class is instantiated. GitHub’s advisory says patched versions throw InvalidTypeIdException before instantiation for the vulnerable payload pattern.(جيثب)

Maven dependency for an affected local test:

<dependencies>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.18.7</version>
  </dependency>
</dependencies>

A minimal local model:

package lab;

import com.fasterxml.jackson.annotation.JsonTypeInfo;

public class Wrapper {
    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
    public Object value;
}

A harmless class that should not be allowed by the PTV:

package lab;

public class DeniedAuditMarker {
    public static boolean wasInstantiated = false;

    public String note;

    public DeniedAuditMarker() {
        wasInstantiated = true;
    }

    public void setNote(String note) {
        this.note = note;
        System.out.println("Setter reached in local lab only: " + note);
    }
}

A local runner:

package lab;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;

public class LocalCve54512Lab {
    public static void main(String[] args) throws Exception {
        BasicPolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
                .allowIfSubType("java.util.ArrayList")
                .build();

        ObjectMapper mapper = JsonMapper.builder()
                .polymorphicTypeValidator(ptv)
                .build();

        String json = """
        {
          "value": [
            "java.util.ArrayList<lab.DeniedAuditMarker>",
            [
              { "note": "local demonstration only" }
            ]
          ]
        }
        """;

        try {
            Wrapper wrapper = mapper.readValue(json, Wrapper.class);
            System.out.println("Result type: " + wrapper.value.getClass());
            System.out.println("DeniedAuditMarker instantiated: " + DeniedAuditMarker.wasInstantiated);
        } catch (Exception e) {
            System.out.println("Deserialization blocked: " + e.getClass().getName());
            System.out.println(e.getMessage());
        }
    }
}

Expected defensive interpretation:

VersionExpected resultالمعنى
Vulnerable line, such as 2.18.7The toy nested class may be instantiatedThe raw container passed while the nested generic parameter was not rejected
Patched line, such as 2.18.8, 2.21.4أو 3.1.4Deserialization should fail before instantiationThe nested generic parameter is validated and blocked
Any version with polymorphic typing removedThe payload shape should not be accepted as class-name type metadataRemoving class-name polymorphism reduces this attack class

The PoC helps defenders understand the boundary. It is not evidence that a production service has RCE. A production exploit would require a reachable endpoint or message path, a compatible type position, and a class with exploitable behavior on the classpath. Those are environment-specific facts and should be proven through authorized testing only.

How to find risky code paths

Dependency scanning answers “is the vulnerable code present?” It does not answer “can an attacker reach the vulnerable deserialization path?” For CVE-2026-54512, reachability review matters because many services include Jackson but never accept attacker-controlled polymorphic class names.

Start with code search:

grep -R "activateDefaultTyping" -n src
grep -R "setDefaultTyping" -n src
grep -R "DefaultTyping" -n src
grep -R "@JsonTypeInfo" -n src
grep -R "JsonTypeInfo.Id.CLASS" -n src
grep -R "JsonTypeInfo.Id.MINIMAL_CLASS" -n src
grep -R "BasicPolymorphicTypeValidator" -n src
grep -R "PolymorphicTypeValidator" -n src
grep -R "allowIfSubType" -n src
grep -R "allowIfBaseType" -n src

Then search for broad receiving types:

grep -R "Object " -n src/main/java
grep -R "Map<.*Object" -n src/main/java
grep -R "List<.*Object" -n src/main/java
grep -R "Serializable" -n src/main/java

These commands are intentionally noisy. They are triage tools, not proof. A field of type الكائن is not automatically vulnerable. A @JsonTypeInfo annotation may be used with logical type names rather than Java class names. A PTV may protect an internal-only format that never crosses a trust boundary. The point is to build a candidate set for manual review.

For each candidate, answer these questions:

  1. Does this mapper handle data from outside the current trust boundary?
  2. Can the caller supply or influence the type id?
  3. Is the type id a Java class name or minimal class name?
  4. Does the configured PTV allow a raw container type such as a collection or map?
  5. Could the caller express a generic type parameter inside that container?
  6. Is the nested class assignable to the expected element, key, value, or parameter position?
  7. Does the classpath contain types with constructor, setter, static initializer, deserialization, lookup, file, network, template, expression, or reflection side effects?
  8. Does the service run with privileges that would make object creation dangerous?

Those questions are more useful than a binary scanner label.

Runtime indicators and logging

A clean production detection story is hard because exploitation may look like malformed JSON, a deserialization exception, or a normal request that produces suspicious side effects. Still, defenders can look for signals.

Useful log patterns include:

الإشارةما أهمية ذلك
Type id strings containing < و >CVE-2026-54512 specifically involves generic type parameters in type identifiers
Type ids naming java.util.ArrayList, java.util.HashMap, or other containersContainer allowlists are a likely bypass surface
Unexpected fully qualified class names in request bodiesClass-name metadata should be rare on public APIs
InvalidTypeIdException after patchingUseful evidence that the patched validator is rejecting unsafe type ids
Sudden deserialization failures after a Jackson upgradeMay show blocked attack attempts or incompatible clients
Outbound network activity during JSON parsingCould indicate gadget side effects or a separate binding issue
Unusual setter-driven state changesObject injection often works through property population

Application logs should avoid recording entire sensitive payloads, but they can safely record normalized security metadata: endpoint, authenticated principal, tenant, source IP, request id, mapper path, exception class, and a sanitized type id hash or prefix. For high-risk services, consider adding explicit logging around deserialization failures involving class-name type ids.

A defensive exception handler might capture enough evidence without leaking payloads:

try {
    return mapper.readValue(input, targetType);
} catch (com.fasterxml.jackson.databind.exc.InvalidTypeIdException e) {
    securityLogger.warn(
        "Blocked polymorphic type id: endpoint={}, requestId={}, baseType={}, typeIdPrefix={}",
        endpointName,
        requestId,
        e.getBaseType(),
        safePrefix(e.getTypeId(), 80)
    );
    throw e;
}

Do not turn this into a verbose payload logger. Attackers often place secrets, probes, or exploit material in request bodies. Logging raw bodies can create a second incident.

Remediation, patch first, then reduce the dangerous design space

The primary fix is to upgrade jackson-databind to a patched version. GitHub’s advisory lists 2.18.8, 2.21.4و 3.1.4 as patched versions for the relevant ranges, and NVD also states that the vulnerability is fixed in those versions.(NVD)

After patching, reduce the design patterns that made the bug dangerous.

Prefer logical type names over Java class names:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = CardPayment.class, name = "card"),
    @JsonSubTypes.Type(value = WirePayment.class, name = "wire")
})
public abstract class PaymentRequest {
}

This model says the API accepts "card" و "wire", not arbitrary Java class names. It is easier to document, easier to test, and less coupled to classpath internals.

Avoid broad الكائن fields in request DTOs:

// Risky at a trust boundary
public class WorkflowStep {
    public Object config;
}

// Safer shape
public class WorkflowStep {
    public String type;
    public Map<String, String> config;
}

When dynamic configuration is unavoidable, validate it as data before constructing privileged objects. JSON Schema, explicit parser code, and narrow DTOs are usually safer than letting a general-purpose object mapper reconstruct arbitrary object graphs.

Keep PTV allowlists narrow even after patching:

BasicPolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
        .allowIfSubType("com.example.safeevents.")
        .build();

Avoid allowlisting broad platform packages, container classes, or third-party namespaces unless there is a strong reason. A container type is not a business type. It is a transport structure. If an API needs to accept a list of safe event types, validate the event types, not merely the list.

Disable global default typing where possible. Jackson’s own documentation says default typing is not encouraged in general and is recommended against when the content source is not trusted.(جيثب)

A migration plan should include:

Remediation layerالإجراءWhy it helps
Dependencyالترقية إلى 2.18.8, 2.21.4أو 3.1.4 or laterRemoves the known vulnerable validation path
API designReplace class-name type ids with logical namesPrevents clients from naming runtime classes
DTO designتجنب الكائن, broad interfaces, and abstract request fieldsReduces polymorphic deserialization need
Validator designNarrow PTV rules to application-owned safe packagesLimits accidental classpath exposure
Mapping designMap request DTOs to domain objects explicitlyPrevents untrusted fields from becoming privileged state
Test designAdd regression tests for rejected type ids and nested genericsProves the fix behavior
LoggingRecord blocked type-id attempts safelySupports detection without leaking payloads
Runtime controlRun services with least privilegeReduces blast radius if object creation has side effects

Regression tests that actually prove the fix

A dependency bump is necessary, but the test suite should prove the vulnerable behavior no longer occurs in the code path that matters to your application. A good regression test does not need a dangerous gadget. It only needs a denied local class and a payload shape that would have bypassed the validator on affected versions.

A JUnit-style test can assert that a nested denied type is rejected:

@Test
void rejectsNestedGenericTypeThatIsNotAllowedByPtv() {
    BasicPolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
            .allowIfSubType("java.util.ArrayList")
            .build();

    ObjectMapper mapper = JsonMapper.builder()
            .polymorphicTypeValidator(ptv)
            .build();

    String json = """
    {
      "value": [
        "java.util.ArrayList<lab.DeniedAuditMarker>",
        [
          { "note": "should not be set" }
        ]
      ]
    }
    """;

    assertThrows(InvalidTypeIdException.class, () -> {
        mapper.readValue(json, Wrapper.class);
    });
}

The test should live near the mapper configuration that production uses. If each service creates its own mapper, each service needs its own test. If a platform team provides a shared mapper, test the shared mapper and still run integration tests in services that accept polymorphic input.

Also add negative tests for the safer design:

@Test
void publicApiDoesNotAcceptClassNameTypeMetadata() {
    String json = """
    {
      "@class": "java.util.ArrayList<lab.DeniedAuditMarker>",
      "value": []
    }
    """;

    assertThrows(Exception.class, () -> {
        publicApiMapper.readValue(json, PublicRequestDto.class);
    });
}

The best test is not “CVE payload blocked.” The best test is “this endpoint never accepts Java class names from clients.”

Why WAF rules are not a real fix

A web application firewall can look for suspicious strings such as java.util.ArrayList< أو @class, and that may be useful as a temporary detection layer. It is not a dependable remediation.

There are several reasons:

WAF limitationSecurity consequence
Type metadata can appear in different wrapper formatsString signatures may miss alternate Jackson inclusion modes
Internal queue and batch paths bypass the WAFDeserialization risk is not limited to public HTTP
Payloads may be encoded, nested, compressed, or transformedEdge inspection may not see the final JSON
Legitimate clients may use polymorphic metadataBlocking can break traffic without proving safety
The vulnerable behavior is inside application deserializationThe application must still be patched

Use edge controls as a short-lived compensating measure only when you cannot patch immediately. The durable fix is a patched jackson-databind, safer mapper configuration, narrower DTOs, and evidence that untrusted JSON cannot supply class-name type ids.

Related Jackson CVEs from the same patch wave

CVE-2026-54512 was disclosed alongside several other Jackson issues. They should not be collapsed into a generic “Jackson is vulnerable” bucket. The response differs by feature and impact.

مكافحة التطرف العنيفFeature areaCore issueDefender focus
CVE-2026-54512Polymorphic deserialization, generic type parametersPTV validates the raw container type but not nested generic type argumentsReview class-name type ids, PTV allowlists, containers, and gadget exposure
CVE-2026-54513BasicPolymorphicTypeValidator.allowIfSubTypeIsArray()Array types can be allowlisted without validating component typesCheck any array-subtype allowlist rules and upgrade
CVE-2026-54514InetSocketAddress bindingDeserializing untrusted JSON into an InetSocketAddress field can trigger attacker-chosen DNS resolution during readValueSearch DTOs with InetSocketAddress; monitor DNS side effects
CVE-2026-54515Case-insensitive binding with per-property ignore rulesIgnored fields can become writable again when case-insensitive deserialization rebuilds the property mapالمراجعة @JsonIgnoreProperties, case-insensitive binding, and sensitive fields
CVE-2026-54518@JsonView, @JsonUnwrapped, creator parametersA specific unwrapped creator path does not consult view visibilityReview view-based write controls and constructor-bound DTOs

CVE-2026-54513 is the closest sibling to CVE-2026-54512. Its GitHub advisory says applications using BasicPolymorphicTypeValidator مع allowIfSubTypeIsArray() get no protection for concrete array component types, because the array wrapper can be accepted while the component type is not validated. It shares the same broader theme: the allowlist decision is made on an outer shape while the dangerous inner type is the one that matters.(جيثب)

CVE-2026-54514 is a different class of problem. NVD describes it as eager DNS resolution when binding untrusted JSON into a type containing an InetSocketAddress field; the fix uses InetSocketAddress.createUnresolved(host, port) to defer DNS resolution until an explicit connect. That is SSRF-adjacent and out-of-band interaction risk, not a PTV generic-parameter bypass.(NVD)

CVE-2026-54515 is different again. GitHub’s advisory says an application that enables case-insensitive matching and relies on per-property @JsonIgnoreProperties to keep a field unwritable can have that field set from untrusted JSON. That is closer to mass assignment or object-binding integrity risk than gadget instantiation.(جيثب) Penligent’s related Jackson write-up on CVE-2026-54515 is useful precisely because it separates that integrity issue from the polymorphic deserialization risk in CVE-2026-54512 and the DNS side effect in CVE-2026-54514.(بنليجنت)

CVE-2026-54518 concerns @JsonView و @JsonUnwrapped creator parameters. GitLab’s advisory explains that buffered JSON is replayed into creator parameters without consulting prop.visibleInView(activeView), allowing a parameter that should be hidden under the active view to be populated from attacker-controlled JSON.(advisories.gitlab.com)

This comparison matters during incident response. If a ticket says “Jackson CVEs,” split it. A PTV bypass, a DNS side effect, an ignored-field write bypass, and a view authorization bypass require different code searches, different regression tests, and different business-impact analysis.

Prioritization for real environments

Patch urgency should be driven by exposure, not just dependency presence. CVE-2026-54512 deserves high priority when any of the following are true:

Priority signalWhy it raises risk
Internet-facing endpoint accepts JSON into polymorphic DTOsRemote untrusted input can reach type resolution
Authenticated low-trust users can submit workflow, connector, or rule JSON“Authenticated” may still mean attacker-controlled in multi-tenant systems
Mapper uses JsonTypeInfo.Id.CLASS or default typingThe client can name Java classes
PTV allows containers or broad package prefixesThe bypass pattern needs an approved outer shell
Application classpath is large and includes legacy librariesMore potential side-effect classes and gadgets
Service has filesystem, network, database, or cloud credentialsObject creation side effects have higher blast radius
Logs show suspicious type ids or deserialization exceptionsThere may already be probing
Vulnerable artifact is embedded in a shared platformOne fix may cover many services, but one miss may expose many tenants

Deprioritize only with written evidence:

Lower-risk evidenceWhat it proves
No vulnerable jackson-databind in runtime artifactThe known vulnerable code path is absent
Polymorphic class-name typing is not enabledThe vulnerable type-id path is not active
Untrusted JSON never reaches the mapperThe trust boundary does not expose the feature
Type ids are logical names with explicit subtype mappingAttackers cannot name arbitrary classes
PTV does not allow raw containers or broad packagesThe known bypass shape is not reachable
Regression tests block nested generic type idsThe patched behavior is verified
Service runs with strict least privilegeWorst-case blast radius is reduced

A scanner cannot usually make those judgments alone. It can identify the dependency and sometimes code patterns. It cannot reliably know whether a queue message is attacker-controlled, whether a tenant-level admin is low trust, whether a shaded JAR is actually loaded, or whether a classpath gadget is reachable in a given deployment.

For authorized teams using AI-assisted validation, this is exactly the kind of CVE where automation should be evidence-driven rather than payload-driven. A useful workflow inventories artifacts, maps reachable JSON boundaries, identifies polymorphic mapper configuration, generates safe local tests, captures upgrade evidence, and produces a report that distinguishes dependency presence from confirmed reachability. Penligent’s public materials describe an agentic security workflow centered on authorized testing, tool orchestration, evidence-first findings, and reproducible reports, which is the right operational shape for this kind of validation when used inside approved scope.(بنليجنت)

Production remediation playbook

CVE-2026-54512 Defensive Validation Workflow

Use a written playbook so closure does not become “we bumped a version somewhere.”

CVE-2026-54512 remediation playbook

Inventory:
  1. Generate Maven or Gradle runtime dependency trees.
  2. Export or inspect SBOMs for all services.
  3. Inspect container images, fat JARs, shaded JARs, and vendor SDKs.
  4. Record artifact path, resolved version, owning team, and deployment target.

Upgrade:
  1. Move Jackson 2.18.x users to 2.18.8 or later.
  2. Move Jackson 2.19-2.21 users to 2.21.4 or later.
  3. Move Jackson 3.x users to 3.1.4 or later.
  4. Prefer framework BOM updates when a framework manages Jackson.
  5. Rebuild and redeploy; do not assume dependency locks updated automatically.

Reachability review:
  1. Search for activateDefaultTyping, setDefaultTyping, DefaultTyping.
  2. Search for @JsonTypeInfo using Id.CLASS or Id.MINIMAL_CLASS.
  3. Search for BasicPolymorphicTypeValidator and custom PTVs.
  4. Identify request, queue, webhook, cache, import, and plugin JSON boundaries.
  5. Mark any low-trust path where type ids can be influenced.

Validation:
  1. Add local regression tests for nested generic type ids.
  2. Confirm patched versions throw before toy denied class instantiation.
  3. Confirm public APIs do not accept Java class-name metadata.
  4. Run staging tests against representative endpoints.
  5. Attach test output to the ticket.

Detection:
  1. Search historical logs for type ids containing generic syntax.
  2. Review deserialization exceptions before and after patching.
  3. Look for unexpected outbound network calls during JSON parsing.
  4. Check audit trails for suspicious object-state changes.
  5. Decide whether incident review is required.

Hardening:
  1. Replace class-name type ids with logical type names where possible.
  2. Remove broad Object fields from untrusted request DTOs.
  3. Narrow PTV allowlists to application-owned safe types.
  4. Add field-level authorization and explicit mapping.
  5. Document approved polymorphic deserialization use cases.

The playbook should be attached to the vulnerability ticket. A closed ticket should contain the old version, fixed version, artifact proof, reachability conclusion, regression test proof, and owner sign-off. Without that evidence, the ticket is not closed; it is merely optimistic.

Common mistakes

The first mistake is treating CVE-2026-54512 as “all Jackson equals RCE.” That overstates the case and causes engineering teams to distrust security findings. The vulnerability requires specific deserialization features and attacker influence over type ids.

The second mistake is treating it as “only a dependency bump.” That understates the case. If an application design still accepts Java class names from untrusted clients, future parser bugs, configuration mistakes, or newly discovered gadget paths can reopen the risk class.

The third mistake is trusting PTV as if it were a sandbox. PTV is a type admission control. It does not make constructors harmless, does not remove setter side effects, does not strip privileges from the process, and does not convert arbitrary object creation into safe data parsing.

The fourth mistake is approving containers instead of business types. A list, map, or array is not a domain object. If a validator approves java.util.ArrayList, it has approved a wrapper, not the safety of the elements.

The fifth mistake is missing shaded copies. Enterprise Java deployments often contain multiple Jackson versions. A service may compile against a fixed version while a plugin, fat JAR, or vendor client ships an older copy.

The sixth mistake is ignoring internal producers. Internal does not mean trusted. A compromised service, tenant-controlled workflow, support upload, webhook relay, or replayed dead-letter message can feed data into a consumer that was never designed for hostile input.

The seventh mistake is closing because no public weaponized exploit is known for your exact stack. CISA ADP’s NVD change history for CVE-2026-54512 records SSVC information with exploitation set to poc, automatable set to no, and technical impact set to total. That is a signal to validate carefully, not a reason to assume exploitation is either universal or impossible.(NVD)

الأسئلة الشائعة

Does CVE-2026-54512 affect every application that uses Jackson?

  • No. A vulnerable jackson-databind version is only the starting point.
  • The main risk appears when polymorphic typing is enabled and untrusted input can influence Java class-name type ids.
  • Applications using Jackson only for ordinary POJO binding without class-name polymorphic type metadata are much less likely to be exposed.
  • Still inventory all runtime artifacts, because frameworks and SDKs may configure mappers outside the code path you first inspect.

Is CVE-2026-54512 remote code execution?

  • It is best described as a PolymorphicTypeValidator bypass that can allow arbitrary class instantiation through generic type parameters.
  • GitHub’s advisory says potential unauthenticated remote code execution can occur when a class with exploitable side effects is present on the classpath.(جيثب)
  • The exact production impact depends on reachability, mapper configuration, assignability, classpath contents, and process privileges.
  • Do not label every finding as confirmed RCE unless you have safe, authorized, environment-specific evidence.

Which jackson-databind versions fix CVE-2026-54512?

  • GitHub lists patched versions 2.18.8, 2.21.4و 3.1.4.
  • Affected ranges include >=2.10.0, <=2.18.7, >=2.19.0, <=2.21.3و >=3.0.0, <=3.1.3 for the com.fasterxml.jackson.core:jackson-databind package.(جيثب)
  • GitHub also lists tools.jackson.core:jackson-databind 3.x through 3.1.3 as affected, fixed in 3.1.4.
  • Verify the version in the deployed artifact, not only the source repository.

How do I know whether polymorphic typing is enabled?

  • البحث عن activateDefaultTyping, setDefaultTyping, DefaultTyping, @JsonTypeInfo, JsonTypeInfo.Id.CLASSو JsonTypeInfo.Id.MINIMAL_CLASS.
  • البحث عن BasicPolymorphicTypeValidator, custom PolymorphicTypeValidator implementations, and allowIfSubType rules.
  • Inspect shared mapper configuration in platform libraries, not just local controllers.
  • Review framework modules, SDKs, plugins, and message consumers that may create their own ObjectMapper.

Can I mitigate CVE-2026-54512 without upgrading?

  • Upgrade is the primary fix.
  • Temporary risk reduction can include disabling class-name polymorphic typing on untrusted input, blocking class-name type metadata at public boundaries, and narrowing PTV allowlists.
  • Those measures are compensating controls, not equivalent to the upstream patch.
  • WAF signatures may help detect suspicious strings but cannot reliably protect queue, batch, internal, encoded, or transformed JSON paths.

How is CVE-2026-54512 different from CVE-2026-54513?

  • CVE-2026-54512 involves generic type parameters, where an allowed raw container can wrap a denied nested type argument.
  • CVE-2026-54513 involves array subtype allowlisting, where the array wrapper can be allowed without validating the component type.
  • Both are PTV-related allowlist bypasses, but the code paths and review questions differ.
  • For CVE-2026-54512, review generic canonical type ids; for CVE-2026-54513, review allowIfSubTypeIsArray() and array component types.(جيثب)

What should a security report include after remediation?

  • The vulnerable and fixed jackson-databind versions.
  • The build or image evidence proving the fixed artifact is deployed.
  • The mapper configuration review, including whether class-name polymorphic typing is present.
  • The trust-boundary analysis for endpoints, queues, imports, webhooks, and plugin paths.
  • Regression test results showing nested generic type ids are rejected.
  • Any detection review, including deserialization exceptions or suspicious type-id patterns.

Why can a scanner flag CVE-2026-54512 but not prove exploitability?

  • SCA tools are good at identifying vulnerable package versions.
  • They usually cannot prove whether untrusted JSON reaches a polymorphic mapper.
  • They may not know whether a type id is attacker-controlled, whether a PTV allowlist approves a relevant container, or whether the runtime classpath contains a useful side-effect class.
  • Treat scanner output as the inventory layer, then add reachability review and safe validation before final risk classification.

Closing judgment

CVE-2026-54512 is a sharp reminder that “we used an allowlist” is not the same as “every type that matters was validated.” The vulnerable Jackson path checked the raw container type and failed to validate nested generic type arguments. That is exactly the kind of bug that slips past shallow dependency triage because the risky configuration can look security-conscious at first glance.

The right response is disciplined and concrete. Upgrade jackson-databind to a fixed release. Prove the deployed artifact changed. Find every place where untrusted JSON can influence polymorphic type ids. Replace Java class-name type metadata with logical names where possible. Stop accepting broad object graphs at low-trust boundaries. Add regression tests that reject nested generic type ids. Preserve enough evidence that another engineer can verify the result later.

For CVE-2026-54512, the patch closes the known library flaw. The larger security lesson is to make object construction boring again: narrow DTOs, explicit mappings, limited type choices, least privilege, and logs that show when the parser refused something it should never have been asked to build.

شارك المنشور:
منشورات ذات صلة
arArabic