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.
# 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
# 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
# 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.

