CVE-2026-91776

Denial of Service
Affects
jackson-databind
in
Jackson
No items found.
Versions
com.fasterxml.jackson.core:jackson-databind: >=2.0.0 <=2.18.10, >=2.19.0 <=2.21.6, >=2.22.0 <=2.22.2; tools.jackson.core:jackson-databind: >=3.0.0 <=3.1.6, >=3.2.0 <=3.2.2

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

jackson-databind is the data-binding package of the FasterXML Jackson suite. It provides the ObjectMapper API that converts JSON and other supported formats to and from Java objects, together with the tree model and the standard serializers and deserializers for common JDK types, and it builds on the low-level streaming parser and generator supplied by jackson-core.

A Denial of Service (DoS) vulnerability (CVE-2026-91776) has been identified in the polymorphic type deserializers of jackson-databind, which allows attackers to grow a process-lifetime cache without bound by feeding a long-lived mapper a stream of distinct unrecognized type ids, retaining memory until the application degrades or fails.

Per OWASP: The Denial of Service (DoS) attack is focused on making a resource (site, application, server) unavailable for the purpose it was designed. There are many ways to make a service unavailable for legitimate users by manipulating network packets, programming, logical, or resources handling vulnerabilities, among others. If a service receives a very large number of requests, it may cease to be available to legitimate users. In the same way, a service may stop if a programming vulnerability is exploited, or the way the service handles resources it uses.

This issue affects the polymorphic type handling of Jackson.

‍

Details

Module Info

Vulnerability Info

This High-severity vulnerability is found in the com.fasterxml.jackson.core:jackson-databind package in the polymorphic type handling of Jackson. Every type deserializer built from @JsonTypeInfo keeps a lazily populated map from type id to resolved deserializer. The map is a plain unbounded concurrent map, it is shared by every contextual copy of the deserializer, and it lives as long as the mapper that owns it:

/**
 * For efficient operation we will lazily build mappings from type ids
 * to actual deserializers, once needed.
 */
protected final Map<String,JsonDeserializer<Object>> _deserializers;
...
// defaults are fine, although shouldn't need much concurrency
_deserializers = new ConcurrentHashMap<String, JsonDeserializer<Object>>(16, 0.75f, 2);

Lookups go through _findDeserializer(), which in the affected releases writes to that map on every resolution path, keyed by the raw type id taken straight from the incoming document:

protected final JsonDeserializer<Object> _findDeserializer(DeserializationContext ctxt,
        String typeId) throws IOException
{
    JsonDeserializer<Object> deser = _deserializers.get(typeId);
    if (deser == null) {
        ...
        JavaType type = _idResolver.typeFromId(ctxt, typeId);
        if (type == null) {
            // use the default impl if no type id available:
            deser = _findDefaultImplDeserializer(ctxt);
            if (deser == null) {
                // 10-May-2016, tatu: We may get some help...
                JavaType actual = _handleUnknownTypeId(ctxt, typeId);
                if (actual == null) { // what should this be taken to mean?
                    return NullifyingDeserializer.instance;
                }
                // ... would this actually work?
                deser = ctxt.findContextualValueDeserializer(actual, _property);
            }
        } else {
            ...
            deser = ctxt.findContextualValueDeserializer(type, _property);
        }
        _deserializers.put(typeId, deser);
    }
    return deser;
}

The terminal _deserializers.put(typeId, deser) is unconditional, and there is no check on the number of entries already held or on the length of the key being stored. The branch that matters is the one taken when _idResolver.typeFromId() returns null, which is what happens for any name the application never registered. A base type annotated with @JsonTypeInfo(use = Id.NAME, defaultImpl = ...) resolves that unknown name to the configured fallback implementation, and the fallback is then cached under the attacker-supplied string. Every distinct unknown name selects the same single deserializer instance, yet each one is retained as its own key. That asymmetry is the attack primitive. An endpoint that deserializes a name-based polymorphic type through a reused ObjectMapper turns each request carrying a fresh unrecognized type id into a permanent map entry, so the cost to the attacker is one short string while the cost to the server is an entry that is never evicted, because nothing in the affected code ever clears or bounds the map. Sending many distinct unknown ids grows retained heap in proportion to the number of unique strings sent, while repeating a single unknown id costs one entry, which is what separates this from ordinary request volume. Because the type id is a JSON string rather than a class name, arbitrarily long ids are accepted as keys as well, so the retained size per entry is also under the requester's control. The result is progressive memory retention that ends in garbage collection pressure, degraded throughput, and eventually an out-of-memory failure of the process.

This vulnerability was introduced in 2012 with jackson-databind 2.0.0.

‍

Mitigation

The affected 2.13.x, 2.14.x, and 2.15.x release lines are End-of-Life and will not receive community updates addressing this issue. Branch status is published on the project's own Jackson Releases page.

Users of the affected components should apply one of the following mitigations:

  • Upgrade jackson-databind to a currently supported release containing the fix, such as 2.18.11 or later.
  • Leverage a commercial support partner like HeroDevs for post-EOL security support.

‍

Credits

Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2026-91776
PROJECT Affected
jackson-databind
Versions Affected
com.fasterxml.jackson.core:jackson-databind: >=2.0.0 <=2.18.10, >=2.19.0 <=2.21.6, >=2.22.0 <=2.22.2; tools.jackson.core:jackson-databind: >=3.0.0 <=3.1.6, >=3.2.0 <=3.2.2
NES Versions Affected
Published date
September 28, 2026
≈ Fix date
September 24, 2026
Category
Denial of Service
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
NES for Jackson
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.