BTC
ETH
SOL
BNB
GOLD
XRP
DOGE
ADA
Back to home
Security

[HIGH] Security Advisory: Jackson Core: Document length constraint bypass in blocking, async, and DataInput parsers (tools.jackson.core:jackson-core)

Jackson Core 3.x, a widely used JSON processing library in Java ecosystems like Spring Boot and Android apps, fails to enforce its StreamReadConstraints.maxDocumentLength limit across multiple...

Jackson Core 3.x, a widely used JSON processing library in Java ecosystems like Spring Boot and Android apps, fails to enforce its StreamReadConstraints.maxDocumentLength limit across multiple parser types. This allows attackers to feed oversized JSON documents—potentially gigabytes—without triggering the expected StreamConstraintsException. The result? Weakened defenses against memory exhaustion denial-of-service (DoS) attacks.

Developers set maxDocumentLength to cap JSON payloads at safe sizes, say 10MB, to prevent servers from choking on malicious input. But in blocking, async, and DataInput parsers, this safeguard crumbles. Oversized docs parse fully, gobbling RAM until the JVM swaps or crashes. In high-traffic services handling untrusted JSON—think APIs, webhooks, or microservices—this turns a tunable knob into a paper tiger.

Vulnerable Code Paths

Three specific flaws expose the bypass. First, blocking parsers like ReaderBasedJsonParser and UTF8StreamJsonParser check document length only after processing complete input buffers. Code at ReaderBasedJsonParser.java:255 and UTF8StreamJsonParser.java:208 increments _currInputProcessed by buffer size and validates then:

_currInputProcessed += bufSize;
_streamReadConstraints.validateDocumentLength(_currInputProcessed);

If the oversized payload fits entirely in the final buffer, no rollover happens. Parsing finishes without a check, accepting the bomb.

Second, async parsers such as NonBlockingByteArrayJsonParser (line 49), NonBlockingByteBufferJsonParser (57), and NonBlockingUtf8JsonParserBase (75) skip validation on the last chunk. They track _currInputProcessed per chunk but call endOfInput() on EOF without a final validation:

_currInputProcessed += _origBufferLen;
_streamReadConstraints.validateDocumentLength(_currInputProcessed());

public void endOfInput() {
    _endOfInput = true;
}

A massive final chunk evades detection, letting async handlers in reactive apps like WebFlux process it unchecked.

Third, the DataInput path via JsonFactory.createParser(DataInput) (line 457) ignores maxDocumentLength entirely. It bootstraps a UTF8DataInputJsonParser that never calls validation. Users pulling JSON from byte streams or legacy inputs get zero protection.

This isn’t subtle. Jackson powers JSON in 70%+ of Java projects per Snyk data. A single unpatched endpoint invites DoS via crafted POSTs or WebSockets.

Proof of Concept and Mitigation

A PoC for the async path demonstrates the issue. It builds a JsonFactory with a 10-byte limit, feeds a 20-byte JSON {"a":1,"b":2}, and parses without exception:

JsonFactory factory = JsonFactory.builder()
    .streamReadConstraints(StreamReadConstraints.builder()
        .maxDocumentLength(10L)
        .build())
    .build();
byte[] doc = "{\"a\":1,\"b\":2}".getBytes(StandardCharsets.UTF_8);
try (JsonParser p = factory.createNonBlockingByteArrayParser(ObjectReadContext.empty())) {
    ByteArrayFeeder feeder = (ByteArrayFeeder) p.getInputFeeder();
    feeder.feedInput(doc, 0, doc.length);
    p.endOfInput();  // No exception thrown despite exceeding 10 bytes
    // Parsing succeeds
}

Fixes land in Jackson 3.x patches—update to the latest 2.17+ or 3.0+ releases immediately. Audit code for custom factories; enable constraints explicitly if not already. Test with fuzzers like JJWT or custom payloads exceeding limits.

Why this matters: JSON APIs are everywhere, from fintech trades to IoT telemetry. A 1GB JSON DoS payload could spike memory from 100MB to 2GB per request, dropping throughput 90% under load. Layered mitigations like nginx client_max_body_size help, but parser-level checks are crucial for backend sanity. This vuln doesn’t steal data—it’s pure disruption—but in production, that’s often enough.

Skeptically, Jackson maintainers fixed similar constraint bugs recently (nesting depth, number length). Credit where due: rapid disclosure via OSS security channels. Still, relying on library constraints demands vigilance; always pair with transport limits and rate limiting. If you’re on Jackson, scan deps now—./gradlew dependencyCheck or OWASP ZAP it.

April 4, 2026 · 3 min · 17 views · Source: GitHub Security

Related