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

CVE-2026-14803: Mojo::JSON Perl DoS Vulnerability

CVE-2026-14803 is a denial of service vulnerability in Mojo::JSON for Perl that causes memory exhaustion through unbounded recursion. This article covers the technical details, affected versions, and mitigation.

Published:

CVE-2026-14803 Overview

CVE-2026-14803 is a denial-of-service vulnerability in Mojo::JSON for Perl, affecting versions before 9.47. The pure-Perl decoder recurses without a depth limit when parsing nested arrays and objects. A small but deeply nested JSON document can exhaust process memory, taking down the affected service.

The flaw only impacts the pure-Perl decode path, which is the default when Cpanel::JSON::XS is not installed or when MOJO_NO_JSON_XS=1 is set. Any endpoint that decodes untrusted JSON input, such as a Mojolicious controller calling $c->req->json, is exposed. The vulnerability is classified under CWE-674 (Uncontrolled Recursion).

Critical Impact

Remote attackers with network access can exhaust server memory by submitting a compact, deeply nested JSON payload to any Mojolicious endpoint that parses untrusted JSON.

Affected Products

  • Mojolicious Mojo::JSON versions before 9.47 (Perl)
  • Applications using the pure-Perl decode path (default when Cpanel::JSON::XS is not installed)
  • Applications explicitly setting MOJO_NO_JSON_XS=1

Discovery Timeline

  • 2026-07-06 - CVE-2026-14803 published to NVD
  • 2026-07-06 - Last updated in NVD database

Technical Details for CVE-2026-14803

Vulnerability Analysis

The vulnerability resides in lib/Mojo/JSON.pm, specifically in the _decode_value function, which dispatches to _decode_array and _decode_object. These functions recursively call _decode_value for each nested element without tracking or bounding recursion depth. Every nesting level consumes Perl stack frames and interpreter memory.

A JSON document consisting of thousands of open brackets, such as [[[[[...]]]]], forces the decoder into deep recursion. Because Perl's call stack and per-frame allocations grow linearly with depth, a payload of only a few kilobytes can consume gigabytes of resident memory, triggering process termination or system-level out-of-memory kills.

Root Cause

The root cause is missing depth accounting in the pure-Perl decoder. Prior to 9.47, Mojo::JSON relied on Perl's default recursion behavior with no warnings 'recursion', but imposed no explicit ceiling. In contrast, the Cpanel::JSON::XS fast path enforces a default 512-level nesting limit and is not affected.

Attack Vector

Any HTTP endpoint that invokes Mojo::Message::json or the exported decode_json on attacker-controlled input is exploitable. Authentication requirements depend on the application, but the attack requires only network reachability and the ability to submit a request body. No user interaction is needed.

text
# From Mojolicious Changes (9.47 UNRELEASED)
- Fixed a security issue where the pure-Perl implementation of Mojo::JSON could exhaust all available memory when
  decoding deeply nested data. Decoding is now limited to 512 levels of nesting, to match the default of
  Cpanel::JSON::XS.

Source: GitHub Patch Commit

perl
# Patch to lib/Mojo/JSON.pm introducing depth tracking
use constant CORE_BOOLS => defined &builtin::is_bool;

# Maximum nesting level for decoding, to match the default of Cpanel::JSON::XS
use constant MAX_DEPTH => 512;

BEGIN {
  warnings->unimport('experimental::builtin') if CORE_BOOLS;
}

# Deep recursion is expected when working with nested data structures
no warnings 'recursion';

our @EXPORT_OK = qw(decode_json encode_json false from_json j to_json true);

# Current nesting level while decoding
our $DEPTH = 0;

Source: GitHub Patch Commit

Detection Methods for CVE-2026-14803

Indicators of Compromise

  • Perl worker processes with rapidly growing resident set size (RSS) shortly after handling an HTTP request
  • Out-of-memory (OOM) killer entries in /var/log/messages or dmesg naming perl, hypnotoad, or morbo processes
  • HTTP requests with unusually deep bracket or brace nesting in request bodies targeting JSON endpoints
  • Web server error logs showing abrupt worker termination without a stack trace during JSON parsing

Detection Strategies

  • Inspect JSON request bodies for excessive nesting depth at a reverse proxy or Web Application Firewall layer before they reach Perl workers
  • Alert on Mojolicious worker processes exceeding baseline memory thresholds during request handling
  • Correlate short-lived request spikes with worker restarts to identify DoS attempts against Mojo::JSON endpoints

Monitoring Recommendations

  • Track per-process memory metrics for hypnotoad, morbo, and plackup workers running Mojolicious applications
  • Monitor HTTP 5xx rates and connection resets on endpoints accepting JSON payloads
  • Log the size and structural characteristics of incoming JSON bodies for anomaly detection

How to Mitigate CVE-2026-14803

Immediate Actions Required

  • Upgrade Mojolicious to version 9.47 or later, which caps decode recursion at 512 levels
  • Install Cpanel::JSON::XS so the unaffected fast path is used by default
  • Verify that MOJO_NO_JSON_XS=1 is not set in production environment variables or service manifests
  • Enforce a maximum request body size on all endpoints that consume JSON via $c->req->json

Patch Information

The fix is included in Mojolicious 9.47, applied in commit cc38b05. It introduces a MAX_DEPTH constant of 512, tracks the current nesting level in $DEPTH, and aborts decoding when the limit is exceeded. See the MetaCPAN Mojolicious Changes and the GitHub Patch Commit for full details. Additional discussion is available on the OpenWall OSS Security Discussion.

Workarounds

  • Install Cpanel::JSON::XS from CPAN so Mojo::JSON automatically uses the XS fast path with its built-in 512-level limit
  • Reject JSON payloads at the proxy layer that exceed a reasonable nesting depth or body size
  • Isolate Mojolicious workers with memory limits via systemdMemoryMax= or container cgroup constraints to contain exhaustion attempts
bash
# Install the XS fast path (unaffected by this CVE)
cpanm Cpanel::JSON::XS

# Ensure the pure-Perl path is not forced
unset MOJO_NO_JSON_XS

# Upgrade Mojolicious to the fixed release
cpanm Mojolicious@9.47

# Optional: constrain worker memory via systemd
# In /etc/systemd/system/myapp.service
# [Service]
# MemoryMax=512M

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

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

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.