GHSA-2m67-wjpj-xhg9
Jackson Core: Document length constraint bypass in blocking, async, and DataInput parsers
Quick fix
GHSA-2m67-wjpj-xhg9 — tools.jackson.core:jackson-core: upgrade to the fixed version with the command below.
# pom.xml: bump <version>3.1.1</version> for tools.jackson.core:jackson-coreDetails
## Summary
Jackson Core 3.x does not consistently enforce `StreamReadConstraints.maxDocumentLength`. Oversized JSON documents can be accepted without a `StreamConstraintsException` in multiple parser entry points, which allows configured size limits to be bypassed and weakens denial-of-service protections.
## Details
Three code paths where `maxDocumentLength` is not fully enforced:
### 1. Blocking parsers skip validation of the final in-memory buffer
Blocking parsers validate only previously processed buffers, not the final in-memory buffer:
- `ReaderBasedJsonParser.java:255` - `UTF8StreamJsonParser.java:208`
Relevant code:
```java _currInputProcessed += bufSize; _streamReadConstraints.validateDocumentLength(_currInputProcessed); ```
This means the check occurs only when a completed buffer is rolled over. If an oversized document is fully contained in the final buffer, parsing can complete without any document-length exception.
### 2. Async parsers skip validation of the final chunk on end-of-input
Async parsers validate previously processed chunks, but do not validate the final chunk on end-of-input:
- `NonBlockingByteArrayJsonParser.java:49` - `NonBlockingByteBufferJsonParser.java:57` - `NonBlockingUtf8JsonParserBase.java:75`
Relevant code:
```java _currInputProcessed += _origBufferLen; _streamReadConstraints.validateDocumentLength(_currInputProcessed);
public void endOfInput() { _endOfInput = true; } ```
`endOfInput()` marks EOF but does not perform a final `validateDocumentLength(...)` call, so an oversized last chunk is accepted.
### 3. DataInput parser path does not enforce `maxDocumentLength` at all
- `JsonFactory.java:457`
Relevant construction path:
```java int firstByte = ByteSourceJsonBootstrapper.skipUTF8BOM(input); return new UTF8DataInputJsonParser(readCtxt, ioCtxt, readCtxt.getStreamReadFeatures(_streamReadFeatures), readCtxt.getFormatReadFeatures(_formatReadFeatures), input, can, firstByte); ```
`UTF8DataInputJsonParser` does not call `StreamReadConstraints.validateDocumentLength(...)`, so `maxDocumentLength` is effectively disabled for `createParser(..., DataInput)` users.
> **Note:** This issue appears distinct from the recently published nesting-depth and number-length constraint advisories because it affects document-length enforcement.
## PoC
### Async path reproducer
```java import java.nio.charset.StandardCharsets; import tools.jackson.core.JsonParser; import tools.jackson.core.ObjectReadContext; import tools.jackson.core.StreamReadConstraints; import tools.jackson.core.async.ByteArrayFeeder; import tools.jackson.core.json.JsonFactory;
public class Poc { public static void main(String[] args) throws 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.nonBlockingInputFeeder(); feeder.feedInput(doc, 0, doc.length); feeder.endOfInput();
while (p.nextToken() != null) { } }
System.out.println("Parsed successfully"); } } ```
- **Expected result:** Parsing should fail because the configured document-length limit is 10, while the input is longer than 10 bytes. - **Actual result:** The document is accepted and parsing completes.
### Blocking path reproducer
```java import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import tools.jackson.core.JsonParser; import tools.jackson.core.StreamReadConstraints; import tools.jackson.core.json.JsonFactory;
public class Poc2 { public static void main(String[] args) throws 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.createParser(new ByteArrayInputStream(doc))) { while (p.nextToken() != null) { } }
System.out.println("Parsed successfully"); } } ```
## Impact
Applications that rely on `maxDocumentLength` as a safety control for untrusted JSON can accept oversized inputs without error. In network-facing services this weakens an explicit denial-of-service protection and can increase CPU and memory consumption by allowing larger-than-configured request bodies to be processed.
Are you affected?
Enter the version of the package you're using.
Affected packages
3.0.0Fixed in: 3.1.1# pom.xml: bump <version>3.1.1</version> for tools.jackson.core:jackson-core