Search for packages
| purl | pkg:maven/com.fasterxml.jackson.core/jackson-core@2.7.7 |
| Vulnerability | Summary | Fixed by |
|---|---|---|
|
VCID-395t-bxwj-7fcu
Aliases: CVE-2025-49128 GHSA-wf8f-6423-gfxg |
Jackson-core Vulnerable to Memory Disclosure via Source Snippet in JsonLocation ### Overview A flaw in Jackson-core's `JsonLocation._appendSourceDesc` method allows up to 500 bytes of unintended memory content to be included in exception messages. When parsing JSON from a byte array with an offset and length, the exception message incorrectly reads from the beginning of the array instead of the logical payload start. This results in possible **information disclosure** in systems using **pooled or reused buffers**, like Netty or Vert.x. ### Details The vulnerability affects the creation of exception messages like: ``` JsonParseException: Unexpected character ... at [Source: (byte[])...] ``` When `JsonFactory.createParser(byte[] data, int offset, int len)` is used, and an error occurs while parsing, the exception message should include a snippet from the specified logical payload. However, the method `_appendSourceDesc` ignores the `offset`, and always starts reading from index `0`. If the buffer contains residual sensitive data from a previous request, such as credentials or document contents, that data may be exposed if the exception is propagated to the client. The issue particularly impacts server applications using: * Pooled byte buffers (e.g., Netty) * Frameworks that surface parse errors in HTTP responses * Default Jackson settings (i.e., `INCLUDE_SOURCE_IN_LOCATION` is enabled) A documented real-world example is [CVE-2021-22145](https://nvd.nist.gov/vuln/detail/CVE-2021-22145) in Elasticsearch, which stemmed from the same root cause. ### Attack Scenario An attacker sends malformed JSON to a service using Jackson and pooled byte buffers (e.g., Netty-based HTTP servers). If the server reuses a buffer and includes the parser’s exception in its HTTP 400 response, the attacker may receive residual data from previous requests. ### Proof of Concept ```java byte[] buffer = new byte[1000]; System.arraycopy("SECRET".getBytes(), 0, buffer, 0, 6); System.arraycopy("{ \"bad\": }".getBytes(), 0, buffer, 700, 10); JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createParser(buffer, 700, 20); parser.nextToken(); // throws exception // Exception message will include "SECRET" ``` ### Patches This issue was silently fixed in jackson-core version 2.13.0, released on September 30, 2021, via [PR #652](https://github.com/FasterXML/jackson-core/pull/652). All users should upgrade to version 2.13.0 or later. ### Workarounds If upgrading is not immediately possible, applications can mitigate the issue by: 1. **Disabling exception message exposure to clients** — avoid returning parsing exception messages in HTTP responses. 2. **Disabling source inclusion in exceptions** by setting: ```java jsonFactory.disable(JsonFactory.Feature.INCLUDE_SOURCE_IN_LOCATION); ``` This prevents Jackson from embedding any source content in exception messages, avoiding leakage. ### References * [Pull Request #652 (Fix implementation)](https://github.com/FasterXML/jackson-core/pull/652) * [CVE-2021-22145 (Elasticsearch exposure of this flaw)](https://nvd.nist.gov/vuln/detail/CVE-2021-22145) |
Affected by 2 other vulnerabilities. |
|
VCID-evmb-e63r-rfcy
Aliases: GHSA-72hv-8253-57qq |
jackson-core: Number Length Constraint Bypass in Async Parser Leads to Potential DoS Condition ### Summary The non-blocking (async) JSON parser in `jackson-core` bypasses the `maxNumberLength` constraint (default: 1000 characters) defined in `StreamReadConstraints`. This allows an attacker to send JSON with arbitrarily long numbers through the async parser API, leading to excessive memory allocation and potential CPU exhaustion, resulting in a Denial of Service (DoS). The standard synchronous parser correctly enforces this limit, but the async parser fails to do so, creating an inconsistent enforcement policy. ### Details The root cause is that the async parsing path in `NonBlockingUtf8JsonParserBase` (and related classes) does not call the methods responsible for number length validation. - The number parsing methods (e.g., `_finishNumberIntegralPart`) accumulate digits into the `TextBuffer` without any length checks. - After parsing, they call `_valueComplete()`, which finalizes the token but does **not** call `resetInt()` or `resetFloat()`. - The `resetInt()`/`resetFloat()` methods in `ParserBase` are where the `validateIntegerLength()` and `validateFPLength()` checks are performed. - Because this validation step is skipped, the `maxNumberLength` constraint is never enforced in the async code path. ### PoC The following JUnit 5 test demonstrates the vulnerability. It shows that the async parser accepts a 5,000-digit number, whereas the limit should be 1,000. ```java package tools.jackson.core.unittest.dos; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; import tools.jackson.core.*; import tools.jackson.core.exc.StreamConstraintsException; import tools.jackson.core.json.JsonFactory; import tools.jackson.core.json.async.NonBlockingByteArrayJsonParser; import static org.junit.jupiter.api.Assertions.*; /** * POC: Number Length Constraint Bypass in Non-Blocking (Async) JSON Parsers * * Authors: sprabhav7, rohan-repos * * maxNumberLength default = 1000 characters (digits). * A number with more than 1000 digits should be rejected by any parser. * * BUG: The async parser never calls resetInt()/resetFloat() which is where * validateIntegerLength()/validateFPLength() lives. Instead it calls * _valueComplete() which skips all number length validation. * * CWE-770: Allocation of Resources Without Limits or Throttling */ class AsyncParserNumberLengthBypassTest { private static final int MAX_NUMBER_LENGTH = 1000; private static final int TEST_NUMBER_LENGTH = 5000; private final JsonFactory factory = new JsonFactory(); // CONTROL: Sync parser correctly rejects a number exceeding maxNumberLength @Test void syncParserRejectsLongNumber() throws Exception { byte[] payload = buildPayloadWithLongInteger(TEST_NUMBER_LENGTH); // Output to console System.out.println("[SYNC] Parsing " + TEST_NUMBER_LENGTH + "-digit number (limit: " + MAX_NUMBER_LENGTH + ")"); try { try (JsonParser p = factory.createParser(ObjectReadContext.empty(), payload)) { while (p.nextToken() != null) { if (p.currentToken() == JsonToken.VALUE_NUMBER_INT) { System.out.println("[SYNC] Accepted number with " + p.getText().length() + " digits — UNEXPECTED"); } } } fail("Sync parser must reject a " + TEST_NUMBER_LENGTH + "-digit number"); } catch (StreamConstraintsException e) { System.out.println("[SYNC] Rejected with StreamConstraintsException: " + e.getMessage()); } } // VULNERABILITY: Async parser accepts the SAME number that sync rejects @Test void asyncParserAcceptsLongNumber() throws Exception { byte[] payload = buildPayloadWithLongInteger(TEST_NUMBER_LENGTH); NonBlockingByteArrayJsonParser p = (NonBlockingByteArrayJsonParser) factory.createNonBlockingByteArrayParser(ObjectReadContext.empty()); p.feedInput(payload, 0, payload.length); p.endOfInput(); boolean foundNumber = false; try { while (p.nextToken() != null) { if (p.currentToken() == JsonToken.VALUE_NUMBER_INT) { foundNumber = true; String numberText = p.getText(); assertEquals(TEST_NUMBER_LENGTH, numberText.length(), "Async parser silently accepted all " + TEST_NUMBER_LENGTH + " digits"); } } // Output to console System.out.println("[ASYNC INT] Accepted number with " + TEST_NUMBER_LENGTH + " digits — BUG CONFIRMED"); assertTrue(foundNumber, "Parser should have produced a VALUE_NUMBER_INT token"); } catch (StreamConstraintsException e) { fail("Bug is fixed — async parser now correctly rejects long numbers: " + e.getMessage()); } p.close(); } private byte[] buildPayloadWithLongInteger(int numDigits) { StringBuilder sb = new StringBuilder(numDigits + 10); sb.append("{\"v\":"); for (int i = 0; i < numDigits; i++) { sb.append((char) ('1' + (i % 9))); } sb.append('}'); return sb.toString().getBytes(StandardCharsets.UTF_8); } } ``` ### Impact A malicious actor can send a JSON document with an arbitrarily long number to an application using the async parser (e.g., in a Spring WebFlux or other reactive application). This can cause: 1. **Memory Exhaustion:** Unbounded allocation of memory in the `TextBuffer` to store the number's digits, leading to an `OutOfMemoryError`. 2. **CPU Exhaustion:** If the application subsequently calls `getBigIntegerValue()` or `getDecimalValue()`, the JVM can be tied up in O(n^2) `BigInteger` parsing operations, leading to a CPU-based DoS. ### Suggested Remediation The async parsing path should be updated to respect the `maxNumberLength` constraint. The simplest fix appears to ensure that `_valueComplete()` or a similar method in the async path calls the appropriate validation methods (`resetInt()` or `resetFloat()`) already present in `ParserBase`, mirroring the behavior of the synchronous parsers. **NOTE:** This research was performed in collaboration with [rohan-repos](https://github.com/rohan-repos) |
Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. Affected by 0 other vulnerabilities. |
|
VCID-pwnn-qx48-ykae
Aliases: CVE-2025-52999 GHSA-h46c-h94j-95f3 |
jackson-core can throw a StackoverflowError when processing deeply nested data ### Impact With older versions of jackson-core, if you parse an input file and it has deeply nested data, Jackson could end up throwing a StackoverflowError if the depth is particularly large. ### Patches jackson-core 2.15.0 contains a configurable limit for how deep Jackson will traverse in an input document, defaulting to an allowable depth of 1000. Change is in https://github.com/FasterXML/jackson-core/pull/943. jackson-core will throw a StreamConstraintsException if the limit is reached. jackson-databind also benefits from this change because it uses jackson-core to parse JSON inputs. ### Workarounds Users should avoid parsing input files from untrusted sources. |
Affected by 1 other vulnerability. |
| Vulnerability | Summary | Aliases |
|---|---|---|
| This package is not known to fix vulnerabilities. | ||