The vulnerability is a prototype pollution issue within the counterpart library, specifically in how it caches processed translation keys. The root cause lies in the _normalizeKey function, which uses a JavaScript object as a cache (this._registry.normalizedKeys) with the translation key separator as one of the cache keys.
An attacker can trigger the vulnerability by calling the main translate function and passing __proto__ as the separator within the options object. Here is the exploitation flow:
translate function is called with a malicious separator, for example: translate('someKey', { separator: '__proto__' }).translate function calls _normalizeKeys, which in turn calls _normalizeKey, passing along the malicious separator._normalizeKey, the code attempts to access the cache using the separator as a key: this._registry.normalizedKeys[separator]. When separator is __proto__, this expression resolves to the Object.prototype of the cache object.this._registry.normalizedKeys[separator][key] = ..., then proceeds to assign a value to a property on Object.prototype instead of the cache object itself. This action pollutes the global Object.prototype for the entire application.The primary vulnerable function is _normalizeKey, where the unsafe caching logic resides. The translate function is the entry point that allows an attacker to supply the malicious input. Any runtime profile or stack trace generated during exploitation would show calls progressing from translate to _normalizeKeys and finally to _normalizeKey, where the prototype pollution occurs.
| Package Name | Ecosystem | Vulnerable Versions | First Patched Version |
|---|---|---|---|
| counterpart | npm | <= 0.18.6 |
Ongoing coverage of React2Shell