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

CVE-2026-48038: joi JavaScript Library DoS Vulnerability

CVE-2026-48038 is a denial of service flaw in joi JavaScript library that allows attackers to crash applications through deeply nested input. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-48038 Overview

CVE-2026-48038 is a denial-of-service vulnerability in joi, a widely used schema description language and data validator for JavaScript. Versions prior to 17.13.4 and 18.2.1 fail to trap a RangeError thrown when recursive link() schemas process deeply nested user input. When a request handler calls validate() without a surrounding try/catch, the unhandled exception can crash the Node.js process. The issue is tracked under [CWE-248: Uncaught Exception] and was addressed in joi releases 17.13.4 and 18.2.1.

Critical Impact

Unauthenticated attackers can submit crafted JSON to trigger an uncaught RangeError in services that validate input with recursive link() schemas, potentially crashing the Node.js process and causing service disruption.

Affected Products

  • joi versions prior to 17.13.4
  • joi versions prior to 18.2.1
  • Node.js applications using recursive link() schemas for JSON or object validation

Discovery Timeline

  • 2026-07-14 - CVE-2026-48038 published to NVD
  • 2026-07-15 - Last updated in NVD database

Technical Details for CVE-2026-48038

Vulnerability Analysis

The flaw resides in the recursive validation path for link() schemas inside lib/types/link.js. When joi validates deeply nested input against a self-referential schema, recursive calls into linked.$_validate() can exhaust the JavaScript call stack. Node.js raises a RangeError: Maximum call stack size exceeded, which joi's link validator did not catch.

Applications that call the synchronous validate() method inside HTTP request handlers propagate that exception up to the Node event loop. Without a surrounding try/catch, the process terminates. Lower-impact paths using validateAsync() or explicit exception handling still surface a raw RangeError rather than a structured ValidationError, breaking downstream error handling.

The vulnerability affects availability only. It does not permit code execution, data disclosure, or integrity impact.

Root Cause

The root cause is an uncaught exception ([CWE-248]) in joi's link resolution logic. The validate function in the link type dispatched to linked.$_validate() without guarding against stack-overflow conditions produced by cyclic or deeply nested references. Any RangeError from that recursion propagated to the caller instead of being converted into a joi validation error.

Attack Vector

A remote, unauthenticated attacker sends a JSON payload with deeply nested structures to any endpoint whose schema uses joi.link() to describe recursive types (for example, tree or comment-thread models). Validation triggers unbounded recursion, and the resulting RangeError bubbles out of the request handler, crashing the Node.js worker.

javascript
// Security patch in lib/types/link.js
// Source: https://github.com/hapijs/joi/commit/fc146a628ab9cc250854407722d9f8738c9548e7

        const linked = internals.generate(schema, value, state, prefs);
        const ref = schema.$_terms.link[0].ref;

        try {
            return linked.$_validate(value, state.nest(linked, `link:${ref.display}:${linked.type}`), prefs);
        }
        catch (err) {
            /* $lab:coverage:off$ */
            if (!(err instanceof RangeError)) {
                throw err;
            }
            /* $lab:coverage:on$ */

            return { value, errors: error('link.depth') };
        }

The patch wraps the recursive $_validate call in a try/catch, converts any RangeError into a structured link.depth validation error, and rethrows unrelated exceptions unchanged. See the GitHub Security Advisory GHSA-q7cg-457f-vx79 and Pull Request #3113 for the upstream fix.

Detection Methods for CVE-2026-48038

Indicators of Compromise

  • Node.js process crashes accompanied by RangeError: Maximum call stack size exceeded in application logs
  • Unhandled promise rejections or uncaught exceptions originating from node_modules/joi/lib/types/link.js
  • Repeated HTTP 502/503 responses following requests carrying unusually large or deeply nested JSON bodies

Detection Strategies

  • Inventory Node.js applications and identify installations of joi prior to 17.13.4 or 18.2.1 using npm ls joi or software composition analysis tooling
  • Search source code for joi.link( usage combined with validate( calls that lack surrounding exception handling
  • Enable Node.js process.on('uncaughtException') and unhandledRejection telemetry to surface stack-overflow crashes tied to validation code

Monitoring Recommendations

  • Alert on abnormal spikes in request body size and JSON nesting depth at the reverse proxy or API gateway
  • Track process restart frequency for Node.js workers and correlate with client IPs sending validation-heavy payloads
  • Forward application error logs to a centralized platform and build queries for RangeError originating in joi modules

How to Mitigate CVE-2026-48038

Immediate Actions Required

  • Upgrade joi to version 17.13.4 (for v17.x deployments) or 18.2.1 (for v18.x deployments)
  • Audit request handlers that invoke joi.validate() on user-supplied input and wrap them in try/catch or migrate to validateAsync() with rejection handling
  • Enforce request size and JSON depth limits at ingress to reduce exposure until patches are deployed

Patch Information

The maintainers fixed the issue in joi 17.13.4 and 18.2.1. Upstream commits 97bd51d and fc146a6 add a try/catch around recursive link validation and emit a structured link.depth error instead of propagating RangeError. Full details are in GHSA-q7cg-457f-vx79.

Workarounds

  • Wrap all joi.validate() calls in try/catch blocks and translate caught RangeError exceptions into HTTP 400 responses
  • Configure body parsers such as express.json() with a conservative limit option to reject oversized payloads
  • Add a pre-validation depth check that rejects JSON exceeding a defined nesting threshold before it reaches joi
bash
# Upgrade joi to a patched release
npm install joi@^17.13.4
# or, for the v18 branch
npm install joi@^18.2.1

# Verify the installed version
npm ls joi

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.