Dev.to Security 🔐 Cybersecurity 👁 0 📖 3 min read

CVE-2026-118772: CVE-2026-118772: Regular Expression Denial of Service in Joi Email Validation

CVE-2026-118772: Regular Expression Denial of Service in Joi Email Validation Vulnerability ID: CVE-2026-118772 CVSS Score: 7.5 Published: 2026-10-30 A Regular Expression Denial of Service (ReDoS) vulnerability exis

CVE-2026-118772: Regular Expression Denial of Service in Joi Email Validation

Vulnerability ID: CVE-2026-118772
CVSS Score: 7.5
Published: 2026-10-30

A Regular Expression Denial of Service (ReDoS) vulnerability exists in the joi schema description and data validation library for JavaScript. When validating multiple email addresses using the Joi.string().email({ multiple: true }) configuration, the library compiles a separator regular expression with an unanchored greedy leading whitespace quantifier. Supplying an input string containing a long sequence of whitespace characters without the expected delimiter triggers quadratic time complexity during String.prototype.split execution, blocking the single-threaded Node.js event loop.

TL;DR

Joi versions prior to 17.13.9 and 18.3.1 are vulnerable to Regular Expression Denial of Service (ReDoS) when validating multiple email addresses via Joi.string().email({ multiple: true }). Unauthenticated attackers can send payloads containing long runs of whitespace to trigger quadratic execution time, freezing the Node.js event loop and causing a denial of service.

⚠️ Exploit Status: POC

Technical Details

  • Vulnerability Class: Regular Expression Denial of Service (CWE-1333)
  • CVSS v3.1 Score: 7.5 High (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
  • Attack Vector: Network (Unauthenticated HTTP Request)
  • Affected Component: Joi.string().email({ multiple: true }) in lib/types/string.js
  • Security Impact: Node.js Event Loop Exhaustion / Remote Denial of Service
  • EPSS Score: 0.47% (40.46th Percentile)
  • Exploit Status: Proof of Concept Available
  • Patched Versions: 17.13.9, 18.3.1

Affected Systems

  • joi
  • @hapi/joi
  • joi: >= 17.1.1, < 17.13.9 (Fixed in: 17.13.9)
  • joi: >= 18.0.0, < 18.3.1 (Fixed in: 18.3.1)
  • @hapi/joi: <= 17.1.1 (Fixed in: 17.13.9 (via migration to joi))

Code Analysis

Commit: 03dc1d9

Primary security fix for 18.x branch replacing greedy leading whitespace quantifier with negative lookbehind in email multiple separator regex

--- a/lib/types/string.js
+++ b/lib/types/string.js
@@ -317,7 +317,9 @@ module.exports = Any.extend({
                 assert(options.multiple === undefined || typeof options.multiple === 'boolean', 'multiple option must be an boolean');

                 const address = internals.addressOptions(options);
-                const regex = new RegExp(`\\s*[${options.separator ? escapeRegex(options.separator) : ','}]\\s*`);
+                // Only start the leading whitespace at the beginning of a run, otherwise the split is quadratic on long whitespace runs,
+                // and only build it when needed since lookbehind requires Safari 16.4+
+                const regex = options.multiple ? new RegExp(`(?:(?<!\\s)\\s+)?[${options.separator ? escapeRegex(options.separator) : ','}]\\s*`) : undefined;

                 return this.$_addRule({ name: 'email', args: { options }, regex, address });
             },

Commit: 807858d

Backport of the email separator ReDoS fix to the 17.x release branch

Mitigation Strategies

  • Upgrade joi to patched versions 17.13.9 or 18.3.1 to replace the vulnerable greedy quantifier with a negative lookbehind assertion.
  • Refactor schemas to use Joi.array().items(Joi.string().email()) instead of Joi.string().email({ multiple: true }) to avoid string splitting via regular expressions.
  • Enforce strict string length limits prior to passing untrusted input into Joi validation pipelines.
  • Avoid using { abortEarly: false } when validating untrusted inputs against schemas that rely on .max() rules to bound expensive downstream checks.

Remediation Steps:

  1. Audit project dependencies using 'npm ls joi' or 'npm audit' to identify vulnerable versions (< 17.13.9 or >= 18.0.0, < 18.3.1) and legacy '@hapi/joi' packages.
  2. Update package.json and lockfiles to require joi@^17.13.9 or joi@^18.3.1.
  3. If immediate patching is blocked, locate all instances of .email({ multiple: true }) in the codebase and add pre-validation length checks or disable 'abortEarly: false' alongside a preceding .max() constraint.
  4. Run regression tests in target browser environments if Joi is bundled for client-side execution to verify compatibility with ES2018 regex lookbehind assertions.

References

Read the full report for CVE-2026-118772 on our website for more details including interactive diagrams and full exploit analysis.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.