Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessSupply attacker-controlled language key via application locale/message endpoint
-
DeliveryApplication passes key into joi schema-construction API (messages/Joi.extend)
-
Exploitexports.compile() or exports.merge() evaluates target[__proto__] without hasOwn check
-
ExecutionProperty written directly onto Object.prototype
-
PersistDownstream authorization or conditional logic checks inherited property
-
ImpactApplication takes unintended code branch
Vulnerability Assessment
| Weakness |
CWE
ASVS 5.0
V3 - Web Frontend Security Prototype pollution prevention
MITRE ATT&CK
2 techniques across 2 tactics: Execution, Initial Access The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Exploitation requires an application to pass attacker-controlled values directly into joi's schema-construction message configuration as language keys - specifically via messages(), message(), prefs({ messages }), Joi.extend({ messages }), or rule({ message }). This is an explicitly non-default pattern: joi's standard usage is to build schemas from static developer-written code and validate untrusted data through those schemas; the vulnerability is not reachable from the validated data path itself. Only applications implementing dynamic, externally configurable locale or message-key support that route external input into schema construction are exploitable. Further limiting exploitation: the incorrect branch outcome depends on downstream application code performing property-existence checks on plain objects, making weaponization application-logic-dependent rather than directly exploitable in all contexts. |
| Impact | The CVSS base score of 3.7 (AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N) is well-calibrated for this vulnerability. High complexity is warranted because exploitation requires an application to actively route untrusted user input into joi's schema-construction message configuration rather than through its normal data validation path - a pattern explicitly noted as non-default in the advisory. No KEV listing exists, no public exploit has been identified at time of analysis, and EPSS data was not provided but would be expected to be low given the restrictive application-level precondition. Real-world risk is bounded: the overwhelming majority of joi consumers build schemas from static, developer-controlled source code and never expose message configuration keys to external input. Applications with dynamic, user-configurable locale support that route externally supplied keys into joi's message APIs represent the realistic at-risk population. The I:L impact is meaningful - prototype pollution can silently flip authorization or conditional logic for any property-existence check in the process - but is not arbitrary code execution and requires an application-specific code path to be weaponized. |
| Exploit ScenarioDerived | An attacker controlling user-supplied locale keys in a multi-language web application submits a key named __proto__ with a nested property such as isAdmin: true through a language preference or message customization endpoint. If the application routes this key into a joi schema's messages() or Joi.extend({ messages }) call without sanitization, exports.compile() writes isAdmin: true onto Object.prototype. All subsequent checks of the form if (obj.isAdmin) anywhere in the process then evaluate to true for every plain object, potentially bypassing authorization gates. No public exploit code has been identified at time of analysis. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Sep 01, 2026
Prototype pollution in joi, one of the most widely used JavaScript schema-validation libraries (versions 16.0.0 through <17.13.6 and <18.2.5, and @hapi/joi through 17.1.1), allows an attacker who can supply attacker-controlled language keys to joi's schema-construction message API to write arbitrary properties onto Object.prototype or the Object constructor's static properties. A language key named __proto__ contaminates the global prototype, causing every subsequent property-existence check on any plain object in the process to return an unexpected value, silently flipping conditional logic. No public exploit has been identified at time of analysis, exploitation conditions are restrictive, and the vendor has released fixed versions 17.13.6 and 18.2.5.
RemediationAI
Upgrade joi to version 17.13.6 (for 17.x users) or 18.2.5 (for 18.x users); both are confirmed fixed releases per the GitHub Security Advisory GHSA-6w3j-5fw6-r9vr and the merged PRs at https://github.com/hapijs/joi/pull/3138 and https://github.com/hapijs/joi/pull/3139. Users still on the legacy @hapi/joi package should migrate to the maintained joi package, as no fixed @hapi/joi version is available or planned. As a compensating control prior to patching, applications should validate and reject message configuration keys equal to __proto__, constructor, or prototype before passing any externally supplied map to joi's messages(), message(), prefs({ messages }), Joi.extend({ messages }), or rule({ message }) APIs; this approach requires careful allowlist logic and carries the trade-off of breaking legitimate locale keys if the filter is misconfigured.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 2 packages in npm
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
joi (cpe:2.3:a:hapijs:joi:*) is the standard schema description and data-validation library for Node.js, originally published as @hapi/joi and later as the standalone joi package. The root cause is CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes), commonly called prototype pollution. In lib/messages.js, both exports.compile() and exports.merge() built per-language message targets with the pattern target[language] = target[language] || {}, which triggers a prototype chain lookup when the language key is __proto__ or constructor. Because JavaScript resolves target['__proto__'] to Object.prototype, the subsequent assignment of per-message-key values writes directly onto Object.prototype rather than creating an own property on the target object. The fix replaces the vulnerable pattern with Object.hasOwn(target, language) to guarantee that only own properties are reused, ensuring that inherited objects on the prototype chain are never mistaken for a legitimate target. The pollution persists for the lifetime of the Node.js worker process, affecting all object literal property-existence checks globally.
Know when Joi gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
AV:N as the schema API is server-side and remotely reachable; AC:H for the non-default requirement of routing untrusted input into message configuration; I:L for prototype pollution enabling wrong-branch logic; C:N and A:N confirmed by the read/write-only nature of the impact.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
Lifecycle Timeline
2DescriptionCVE.org
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.
Blast Radius
ecosystem impact- 9 npm packages depend on @hapi/joi (3 direct, 6 indirect)
- 4 npm packages depend on joi (4 direct, 0 indirect)
Ecosystem-wide dependent count for version 16.0.0 and other introduced versions.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Joi, the JavaScript schema validation library published on npm as joi (17.1.1 through 17.13.8, and 18.0.0 through 18.3.0
Prototype pollution in hapijs/joi's messages compilation function allows network-reachable attackers to replace an objec
Limited prototype pollution in joi's object().rename() allows unauthenticated remote attackers to set the prototype of t
EUVD-2026-69649
GHSA-6w3j-5fw6-r9vr
NVD
CVE.org
EPSS
Vulnrichment
Exploit-DB