Summary
### Summary `Joi.string().email({ multiple: true })` takes quadratic time to split a value that contains a long run of whitespace. One request with 100 KB of spaces blocks the Node.js event loop for several seconds, which causes a denial of service. ### Details When the `multiple` option is set, the `email` rule splits the value into addresses with a regular expression that removes whitespace on each side of the separator: ```js const regex = new RegExp(`\\s*[${options.separator ? escapeRegex(options.separator) : ','}]\\s*`); // ... const emails = options.multiple ? value.split(regex) : [value]; ``` `String.prototype.split` tries a match at each position of the value. At each position inside a whitespace run, the leading `\s*` reads the rest of the run, does not find a separator, and backtracks through all of it. A run of `n` whitespace characters without a separator therefore costs `n²` steps. This applies to the default separator and to all custom `separator` values. The fix lets the leading whitespace match start only at the beginning of a whitespace run, so the split is linear: ```js const regex = new RegExp(`(?:(?<!\\s)\\s+)?[${options.separator ? escapeRegex(options.separator) : ','}]\\s*`); ``` The split results do not change. The regular expression is now built only when `multiple` is set. Every `joi` release from `17.1.1` up to and including `17.13.8`, and from `18.0.0` up to and including `18.3.0`, is affected. Every `@hapi/joi` release from `16.0.0` is affected. Workarounds for users who cannot upgrade: - Add `.max()` before `.email()`, for example `Joi.string().max(1000).email({ multiple: true })`. The `max` rule then rejects long values before the `email` rule runs. - Do not use the `abortEarly: false` option with this schema. With `abortEarly: false`, the `email` rule runs even when the `max` rule fails. - Do not use `.trim()` as a workaround. It removes only the whitespace at the start and at the end of the value. ### Proof of concept ```js const Joi…
Remediation
References
- Advisoryhttps://github.com/advisories/GHSA-4528-x5fx-h6hg
- Referencehttps://github.com/hapijs/joi/security/advisories/GHSA-4528-x5fx-h6hg
- Referencehttps://nvd.nist.gov/vuln/detail/CVE-2026-118772
- Referencehttps://github.com/hapijs/joi/pull/3162
- Referencehttps://github.com/hapijs/joi/pull/3163
- Referencehttps://github.com/hapijs/joi/commit/03dc1d909818503b06240dadc81e9227ed2649cf
- Referencehttps://github.com/hapijs/joi/commit/807858d7480f5075b0610817e3e44230890fb18e
- Referencehttps://github.com/hapijs/joi/releases/tag/v17.13.9
- Referencehttps://github.com/hapijs/joi/releases/tag/v18.3.1