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:
- 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.
- Update package.json and lockfiles to require joi@^17.13.9 or joi@^18.3.1.
- 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.
- Run regression tests in target browser environments if Joi is bundled for client-side execution to verify compatibility with ES2018 regex lookbehind assertions.
References
- GitHub Security Advisory GHSA-4528-x5fx-h6hg
- NVD - CVE-2026-118772
- CVE.org Record - CVE-2026-118772
- Joi Fix Commit (18.x) - 03dc1d909818503b06240dadc81e9227ed2649cf
- Joi Fix Commit (17.x) - 807858d7480f5075b0610817e3e44230890fb18e
- GitHub Pull Request #3162
- GitHub Pull Request #3163
- Joi Release v17.13.9
- Joi Release v18.3.1
Read the full report for CVE-2026-118772 on our website for more details including interactive diagrams and full exploit analysis.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.