CVE-2026-59990 Overview
CVE-2026-59990 is a denial-of-service vulnerability in Jawn, an open source JSON parser for Scala maintained by the Typelevel project. Versions prior to 1.7.0 accept arbitrarily deep JSON array and object nesting because the parser does not enforce a depth limit. A remote attacker who can submit untrusted JSON can grow parser contexts until the Java Virtual Machine (JVM) heap is exhausted. The resulting java.lang.OutOfMemoryError is a fatal Scala error that is not caught by scala.util.Try or cats.effect.IO, terminating the process. The issue is fixed in Jawn 1.7.0 and is tracked as [CWE-770] Allocation of Resources Without Limits or Throttling.
Critical Impact
A single crafted JSON payload with deeply nested arrays or objects can crash any service that parses untrusted input with Jawn, disrupting availability of dependent Scala and cats-effect applications.
Affected Products
- Typelevel Jawn JSON parser versions prior to 1.7.0
- Scala applications that use Jawn parse methods on untrusted input
- Downstream libraries wrapping Jawn parsing under scala.util.Try or cats.effect.IO
Discovery Timeline
- 2026-09-23 - CVE-2026-59990 published to the National Vulnerability Database (NVD)
- 2026-09-23 - Last updated in NVD database
Technical Details for CVE-2026-59990
Vulnerability Analysis
Jawn parses JSON using a recursive descent strategy in parser/shared/src/main/scala/jawn/Parser.scala. Each opening [ or { token pushes a new FContext[J] onto an internal stack that tracks the current container. Prior to 1.7.0, the parser accepted unbounded nesting depth, allowing a caller to keep pushing contexts until the JVM heap is exhausted.
When the heap fills, the JVM raises java.lang.OutOfMemoryError. Unlike ParseException, this is a fatal Throwable that neither scala.util.Try nor cats.effect.IO catches by default. Services that rely on those effect types to isolate parsing failures instead see the entire process terminate, producing denial of service.
Root Cause
The root cause is missing input validation on nesting depth during recursive parsing. The rparse routine appended context frames without checking a maximum depth constant, and there was no mechanism to short-circuit pathological input. This maps to [CWE-770] Allocation of Resources Without Limits or Throttling.
Attack Vector
Attack requires only network access to an endpoint that forwards untrusted JSON into a Jawn parse call. Authentication and user interaction are not required. A payload consisting of thousands of unmatched [ characters is sufficient to trigger heap exhaustion on a typical JVM configuration.
// Patch: enforce configurable maximum nesting depth
// parser/shared/src/main/scala/jawn/Parser.scala
object Parser extends ParserCompanionPlatform {
- final val DefaultMaxDepth = 4096
+ val DefaultMaxDepth: Int =
+ Try(System.getProperty("jawn.parser.maxDepth").toInt).getOrElse(4096)
def parseUnsafe[J](s: String)(implicit facade: Facade[J]): J =
new StringParser(s).parse()
}
// New exception type raised when the depth cap is exceeded
class MaxDepthExceededException(index: Int, line: Int, col: Int, val maxDepth: Int)
extends ParseException("max depth exceeded", index, line, col)
Source: GitHub Jawn Commit 191cb3a4 and GitHub Jawn Commit 93ac93e.
Detection Methods for CVE-2026-59990
Indicators of Compromise
- Application logs containing java.lang.OutOfMemoryError originating from jawn.Parser or rparse frames.
- Abrupt JVM process termination shortly after receiving JSON payloads from external clients.
- Inbound HTTP requests carrying JSON bodies with unusually large runs of [ or { characters and minimal payload entropy.
Detection Strategies
- Inspect application dependency manifests (build.sbt, pom.xml, generated lockfiles) for org.typelevel:jawn-parser versions below 1.7.0.
- Add web application firewall (WAF) or API gateway rules that reject JSON bodies exceeding a reasonable nesting depth or raw size.
- Correlate JVM crash telemetry with the preceding HTTP request to identify pathological payload sources.
Monitoring Recommendations
- Track JVM heap utilization and OutOfMemoryError counts per service and alert on sudden spikes.
- Monitor request rates from single source IPs against JSON parsing endpoints for burst patterns.
- Emit and centralize structured logs from Jawn's new MaxDepthExceededException once patched, so blocked payloads are visible in the security data lake.
How to Mitigate CVE-2026-59990
Immediate Actions Required
- Upgrade Jawn to version 1.7.0 or later across all Scala services and transitive dependencies.
- Audit downstream libraries such as circe, http4s, and play-json integrations that depend on Jawn and rebuild with the patched version.
- Enforce request body size limits at the HTTP layer to reduce the attack surface for oversized JSON.
Patch Information
The fix is available in Jawn Release v1.7.0. The patched parser enforces a configurable DefaultMaxDepth (4096 by default) that can be tuned with the jawn.parser.maxDepth system property, and raises a new MaxDepthExceededException instead of exhausting the heap. Additional commits 6219666 and f6ace7e harden the deprecated rparse entry point. Full advisory details are in the GitHub Security Advisory GHSA-cc4v-rvgp-2pf3.
Workarounds
- If upgrading immediately is not possible, reject JSON payloads at an upstream proxy when nesting depth or body length exceeds a service-appropriate threshold.
- Wrap parsing calls in a bounded thread pool with strict JVM heap limits so that a crash affects an isolated worker rather than the primary service.
- Terminate connections that submit repeated malformed JSON from the same source using existing rate-limiting controls.
# Configuration example: tune the Jawn depth cap at JVM startup
java -Djawn.parser.maxDepth=256 -Xmx1g -jar my-scala-service.jar
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

