CVE-2026-89407
High · 7.5CVSS
7.5
EPSS
0.5%
Published
Sep 22, 2026
CISA due date
—
Cloudanix analysis
A popular JSON reading library can be forced to freeze and stop serving users when it is given very long fake numbers.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Low
- Impact
- Denial Of Service
- Component
- Library
- Class
- Denial of service
- Remediation
- Upgrade
- Effort
- Low
- Patch risk
- None
What it actually does
FasterXML jackson-core 2.17.x NumberInput.looksLikeValidNumber() pre-validates stringified numbers with PATTERN_FLOAT (since 2.17.0) and PATTERN_FLOAT_TRAILING_DOT (since 2.17.2). Adjacent quantifiers over the same digit class force Java's regex engine into O(n^2) backtracking on non-matching input. jackson-databind's default String-to-number coercion (StdDeserializer and NumberDeserializers for BigDecimal, BigInteger, Double, and Float) reaches this method. StreamReadConstraints.maxStringLength defaults to 20,000,000, so no practical bound is applied before the regex. A single large string can pin a worker thread for tens of seconds; concurrent requests exhaust the request-handling pool. 2.16.x and earlier lack the method and are not affected. The fix replaces both regular expressions with a linear single-pass scan.
Why it matters to the business
Remote unauthenticated callers can render JSON-processing services unavailable by saturating CPU and request threads, causing timeouts, failed transactions, and SLA breaches. Impact is availability-only (no confidentiality or integrity loss). The issue is not on CISA KEV, has no known ransomware use, exploit maturity is none, and EPSS remains low (~0.0055, flat over 30 days), but any internet-facing app that deserializes untrusted JSON with jackson-core 2.17.x is still exposed. About 20 days have elapsed since publication, so remaining unpatched 2.17.x estates should still be treated as an active availability risk.
How an attack unfolds
An attacker finds an endpoint that accepts JSON and binds string values to numeric Java types through jackson-databind. They send a body containing a very long digit-heavy string that looks like a number but does not satisfy the float patterns. Because the default max string length is extremely high, the full value reaches looksLikeValidNumber(). The matcher retries every split of the digit run, so CPU cost grows with the square of length and a worker thread stays blocked far longer than a normal parse. A small number of concurrent requests of ordinary body size can fill the thread pool until legitimate traffic fails. No privileges or user interaction are required on a reachable endpoint. No named threat actors or campaigns are associated, and there is no public exploit maturity.
How to fix it
Upgrade jackson-core off affected 2.17.x builds to a patched release in which NumberInput.looksLikeValidNumber() uses the hand-rolled single-pass scan instead of PATTERN_FLOAT and PATTERN_FLOAT_TRAILING_DOT (2.16.x and earlier are not affected). Refresh jackson-databind and other FasterXML artifacts so they do not pull a vulnerable jackson-core transitively. If an immediate upgrade is not possible, lower StreamReadConstraints.maxStringLength well below the 20,000,000 default, enforce HTTP body and field-size limits in front of the parser, avoid coercing untrusted strings into numeric types, and apply request-rate and concurrency limits on JSON endpoints. Rebuild and redeploy all artifacts after the dependency change.
How to confirm the fix worked
Inventory production and CI dependency trees for com.fasterxml.jackson.core:jackson-core 2.17.0 and later that still contain PATTERN_FLOAT / PATTERN_FLOAT_TRAILING_DOT in NumberInput. Confirm the resolved jackson-core jar is a patched build whose looksLikeValidNumber() is a linear scan, not regex. Verify StreamReadConstraints.maxStringLength and HTTP body limits are set to values appropriate for the API. After upgrade, regression-test JSON numeric deserialization (including stringified numbers) for functional correctness and confirm parse threads no longer show regex Matcher frames on number validation. Do not use adversarial oversized inputs in production to prove the old behavior.
Typical attack path
- Identify a network-reachable service that deserializes untrusted JSON into numeric Java types with jackson-databind and jackson-core 2.17.x.
- Send JSON in which a field destined for BigDecimal, BigInteger, Double, or Float is a very long string that resembles a number but fails the float validation patterns.
- Allow jackson-core NumberInput.looksLikeValidNumber() to run the vulnerable regular expressions without a tight maxStringLength bound.
- Issue a small number of concurrent requests so quadratic matching occupies request-handling threads.
- Sustain the load until the thread pool is exhausted and legitimate requests time out or fail.
How to detect it
There is no public exploit, named actor, or ransomware campaign to hunt. Look for availability incidents: request-thread pool exhaustion, elevated CPU in JSON parse workers, and timeouts on endpoints that deserialize JSON to numeric types, especially if traffic volume is not correspondingly high. Thread dumps and profilers during an incident may show com.fasterxml.jackson.core.io.NumberInput.looksLikeValidNumber, java.util.regex.Matcher / Pattern on jackson parse threads, or NumberDeserializers / StdDeserializer frames. Access and application logs may show unusually large JSON bodies or string fields on numeric targets. Compare jackson-core versions on affected hosts (2.17.x in-scope; pre-2.17.0 not in-scope). Absence of these artifacts does not prove the service was never targeted; it only means no leftover regex-DoS signature is expected on disk.
- com.fasterxml.jackson.core.io.NumberInput.looksLikeValidNumber
- com.fasterxml.jackson.databind.deser.std.NumberDeserializers
- com.fasterxml.jackson.databind.deser.std.StdDeserializer
- java.util.regex.Matcher.matches
- jackson-core-2.17.
What your security team should do
- Immediately inventory applications and libraries resolving jackson-core 2.17.0 or later; treat 2.17.x as in-scope even though this CVE is not KEV and EPSS is low.
- Upgrade jackson-core to a patched release that replaces the number-validation regexes with a single-pass scan, and pin the version so vulnerable 2.17.x cannot re-enter via transitives.
- Tighten StreamReadConstraints.maxStringLength and HTTP body/field size limits so untrusted strings cannot approach multi-megabyte validation.
- Add or lower rate, concurrency, and request-timeout controls on JSON endpoints that bind to numeric types.
- Monitor request-thread pools and jackson parse CPU for saturation while patches roll out; 2.16.x and earlier need no code change for this specific flaw.
The record
NumberInput.looksLikeValidNumber() in FasterXML jackson-core pre-validates "stringified numbers" with two regular expressions: PATTERN_FLOAT ([+-]?[0-9]*[\.]?[0-9]+([eE][+-]?[0-9]+)?), present since 2.17.0, and PATTERN_FLOAT_TRAILING_DOT, added in 2.17.2. PATTERN_FLOAT places adjacent quantifiers over the same character class -- an optional [0-9]* run, an optional dot, then a required [0-9]+ run -- so input that ultimately fails to match forces Java's backtracking engine to retry every possible split point of the digit run. Matching cost therefore grows with the square of the input length. An attacker who can supply JSON that an application deserializes into a numeric target type reaches this method through jackson-databind's default String-to-number coercion (StdDeserializer and NumberDeserializers for BigDecimal, BigInteger, Double and Float). Because StreamReadConstraints.maxStringLength defaults to 20,000,000 characters, no constraint bounds the input before it reaches the regex. Testing by the reporter confirmed O(n^2) growth across five consecutive input-size doublings, with a single 160,000-character string consuming roughly 74 seconds in one call; a small number of concurrent requests of ordinary body size can therefore exhaust a server's request-handling thread pool. The affected method does not exist before 2.17.0, so 2.16.x and earlier releases are not affected. The fix replaces both regular expressions with a hand-rolled single-pass scan.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|
Related vulnerabilities
- CVE-2026-113795 pypdf is a free and open-source pure-python PDF library. CWE-400
- CVE-2026-83400 Vulnerability in the Oracle Java SE, Oracle GraalVM for JDK, Oracle GraalVM Enterprise… CWE-400
- CVE-2026-112400 Pillow is a Python imaging library. CWE-400
- CVE-2026-111766 markdown-it is a Markdown parser. CWE-400
- CVE-2026-111759 markdown-it is a Markdown parser. CWE-400
- CVE-2025-52290 A NULL pointer dereference in the avpriv_h264_has_num_reorder_frames function of Ffmpeg… CWE-400
- CVE-2026-111066 AIOHTTP is an asynchronous HTTP client/server framework for asyncio and Python. CWE-400
- CVE-2026-59951 The MCP Python SDK, called mcp on PyPI, is a Python implementation of the Model Context… CWE-400