CVE-2026-84368: joi: Prototype pollution via a `__proto__` language key in custom messages
Impact An application that passes attacker-controlled data into joi's custom message configuration (messages(), message(), prefs({ messages }), Joi.extend({ messages }) or rule({ message })) lets the attacker write properties onto Object.prototype, where every object in the process then inherits them. A key named proto was treated as a language name, and the code reused the object it found at that key, which resolves to the prototype rather than to a new own property; a key named constructor did the same to the Object function's statics. A consuming application that gates on the mere presence of a property (if (user.isAdmin)) can be made to take the wrong branch for every object it inspects.
This is not reachable from data that joi validates. Custom messages are schema-construction configuration, normally written by the application developer. Exploitation therefore requires an application that feeds untrusted input straight into schema construction.
Patches Upgrade to version 18.2.5 or 17.13.6.
Workarounds Do not pass untrusted input into messages(), message(), prefs({ messages }), Joi.extend({ messages }) or rule({ message }). Or validate that they don't contain any proto or constructor property.
Other sources
Joi 17.13.6 before 17.13.9 and 18.2.5 before 18.3.1 contains a prototype pollution vulnerability in lib/messages.js compile() and merge() that fails to reject a proto language key. Attackers supplying untrusted message configuration via any().messages(), prefs, validate options or Joi.extend can replace the compiled messages prototype, altering or breaking validation error rendering and dependent logic.
— OSV
joi is a schema description language and data validator for JavaScript. From 16.0.0 until 17.13.6 and 18.2.5, the @hapi/joi package through 17.1.1 and the successor joi package contain prototype pollution in lib/messages.js, where exports.compile() and exports.merge() reuse inherited objects for attacker-controlled language keys supplied through messages(), message(), prefs({ messages }), Joi.extend({ messages }), or rule({ message }). A language key named proto writes properties onto Object.prototype, and constructor writes to the Object function's static properties. A consuming application that gates on the presence of an inherited property can take the wrong branch for every inspected object. The flaw is not reachable from data that joi validates and requires an application to feed untrusted input directly into schema-construction configuration. This issue is fixed in joi versions 17.13.6 and 18.2.5; no fixed @hapi/joi version is available.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/joito a version that resolves this vulnerability.Fixed in 18.2.5 - Upgrade
Upgrade
npm/joito a version that resolves this vulnerability.Fixed in 17.13.6 - Upgrade
Upgrade
joito a version that resolves this vulnerability.Fixed in 17.13.6 - Upgrade
Upgrade
joito a version that resolves this vulnerability.Fixed in 18.2.5 - Compensating control
Do not pass untrusted input into joi custom message configuration APIs, including messages(), message(), prefs({ messages }), Joi.extend({ messages }), validate options, or rule({ message }); validate configuration objects to ensure they do not contain __proto__ or constructor properties.
Event History
Frequently Asked Questions
Which applications are realistically exposed to this issue?
Applications are exposed only if they pass untrusted input directly into Joi schema-construction message configuration, including messages(), message(), prefs({ messages }), Joi.extend({ messages }), or rule({ message }). Data being validated by Joi does not reach the vulnerable path.
What does an attacker need to provide to exploit it?
An attacker needs control over a language key in custom message configuration and must be able to supply a key named __proto__. Exploitation can pollute Object.prototype, potentially causing applications that test inherited properties to take an incorrect branch.
Are default Joi configurations affected?
The issue requires attacker-controlled custom message language keys during schema construction. The provided information does not indicate that ordinary validation input or a configuration without untrusted message definitions is affected.
What versions should be used to remediate the issue?
Upgrade joi to version 17.13.6 or 18.2.5. No fixed version is available for @hapi/joi.
What can be done if upgrading is not immediately possible?
Do not feed untrusted input into Joi custom-message or schema-construction configuration. In particular, prevent attacker-controlled language keys from reaching the listed message configuration APIs.