Skip to main content
Vulnerability Database/CVE-2026-89407

CVE-2026-89407: FasterXML jackson-core DOS Vulnerability

CVE-2026-89407 is a denial of service flaw in FasterXML jackson-core caused by inefficient regex validation that leads to quadratic processing time. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-89407 Overview

CVE-2026-89407 is a regular expression denial-of-service (ReDoS) vulnerability in FasterXML jackson-core. The flaw resides in NumberInput.looksLikeValidNumber(), which pre-validates stringified numbers using two regular expressions: PATTERN_FLOAT (present since 2.17.0) and PATTERN_FLOAT_TRAILING_DOT (added in 2.17.2). Adjacent quantifiers over the same digit character class force Java's backtracking engine to retry every possible split of the digit run when a match ultimately fails. Matching cost grows with the square of input length. Attackers who submit JSON that an application deserializes into a numeric target type reach the method via jackson-databind String-to-number coercion, exhausting request-handling threads. Releases before 2.17.0 do not contain the affected method and are not vulnerable.

Critical Impact

A small number of concurrent requests carrying ordinary-sized JSON bodies can saturate a server's thread pool and take the application offline.

Affected Products

  • FasterXML jackson-core 2.17.0 through 2.17.1 (PATTERN_FLOAT only)
  • FasterXML jackson-core 2.17.2 and later 2.x releases prior to the fix (both regex patterns)
  • Applications using jackson-databind with default StreamReadConstraints.maxStringLength of 20,000,000 characters that deserialize into BigDecimal, BigInteger, Double, or Float

Discovery Timeline

  • 2026-09-22 - CVE-2026-89407 published to NVD
  • 2026-09-22 - Last updated in NVD database

Technical Details for CVE-2026-89407

Vulnerability Analysis

The vulnerability is an algorithmic complexity flaw [CWE-400] in the pre-validation step of stringified numeric parsing. NumberInput.looksLikeValidNumber() applies PATTERN_FLOAT, defined as [+-]?[0-9]*[\.]?[0-9]+([eE][+-]?[0-9]+)?, to candidate numeric strings before conversion. The pattern places an optional [0-9]* run, an optional dot, and a required [0-9]+ run adjacent to one another, all matching the same digit character class. When the overall input fails to satisfy the trailing constraints (for example, the exponent or terminator), Java's backtracking regex engine retries every possible partition of the digit run between the two quantifiers. The reporter confirmed O(n²) growth across five consecutive input-size doublings, with a single 160,000-character string consuming roughly 74 seconds in one call.

Root Cause

The root cause is ambiguous quantifier composition over identical character classes. [0-9]* followed by an optional dot and [0-9]+ allows any digit in the input to belong to either quantified group, producing exponential backtracking states in the worst case and quadratic time on failure paths. No upstream length constraint bounds the input reaching the regex, because StreamReadConstraints.maxStringLength defaults to 20,000,000 characters.

Attack Vector

Any HTTP or messaging endpoint that deserializes attacker-controlled JSON into a numeric Java type triggers the vulnerable path. StdDeserializer and the NumberDeserializers for BigDecimal, BigInteger, Double, and Float invoke looksLikeValidNumber() during String-to-number coercion. An attacker submits a JSON document containing a long stringified numeric field crafted to fail final validation, forcing the regex into its quadratic path. Concurrent submissions saturate the server thread pool, producing a denial-of-service condition without authentication or user interaction.

See the GitHub Security Advisory GHSA-p6pp-m3f8-5c89 and GitHub Issue #1649 for the reporter's reproduction data.

Detection Methods for CVE-2026-89407

Indicators of Compromise

  • JSON request bodies containing unusually long numeric string fields, particularly values exceeding several thousand characters composed largely of digits.
  • Application threads blocked inside com.fasterxml.jackson.core.io.NumberInput.looksLikeValidNumber visible in thread dumps or profiler output.
  • Sudden increases in request latency or thread pool saturation correlated with JSON parsing endpoints.

Detection Strategies

  • Inspect Java stack traces and flight recordings for CPU time concentrated in java.util.regex.Pattern$Curly.match invoked from NumberInput.
  • Alert on inbound JSON payloads where any string field exceeds a defensible size threshold (for example, 1,000 characters) for numeric targets.
  • Correlate spikes in per-request CPU time against endpoints that bind JSON to BigDecimal, BigInteger, Double, or Float fields.

Monitoring Recommendations

  • Instrument JSON parsing endpoints with per-request CPU and wall-clock timers and alert on outliers.
  • Track thread pool utilization on application servers and generate alerts when active threads exceed sustained thresholds.
  • Enable web application firewall logging on request body size and character composition for JSON endpoints.

How to Mitigate CVE-2026-89407

Immediate Actions Required

  • Upgrade jackson-core to the patched release identified in GitHub Security Advisory GHSA-p6pp-m3f8-5c89.
  • Reduce StreamReadConstraints.maxStringLength on all JsonFactory instances to a value appropriate for the application, well below the 20,000,000 default.
  • Audit deserialization targets and remove unbounded BigDecimal, BigInteger, Double, and Float bindings where numeric input is untrusted.

Patch Information

The fix replaces both PATTERN_FLOAT and PATTERN_FLOAT_TRAILING_DOT with a hand-rolled single-pass scan that runs in linear time. Review GitHub Pull Request #1650 and GitHub Pull Request #1701 for the implementation. Applications on jackson-core 2.16.x or earlier are not affected and do not require this patch.

Workarounds

  • Apply a custom StreamReadConstraints with a reduced maxStringLength (for example, 10,000 characters) globally on shared ObjectMapper instances.
  • Enforce request body size limits and per-field length validation at the web tier or API gateway before JSON reaches Jackson.
  • Deploy WAF rules that reject JSON documents containing string fields exceeding a defined digit-run length when targeting known numeric endpoints.
bash
# Configuration example: constrain Jackson string length globally
StreamReadConstraints constraints = StreamReadConstraints.builder()
    .maxStringLength(10_000)
    .build();
JsonFactory factory = JsonFactory.builder()
    .streamReadConstraints(constraints)
    .build();
ObjectMapper mapper = new ObjectMapper(factory);

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.