Summary
Versions of i18next-http-middleware prior to 3.9.3 allow an unauthenticated HTTP client to pollute Object.prototype in the Node.js process hosting the middleware, via two unvalidated entry points that reach internal object-key writes:
getResourcesHandler — reads lng / ns from query parameters or route params and passes them to utils.setPath(resources, [lng, ns], value). The setPath helper walked the key path without guarding against __proto__, constructor, or prototype keys, so a request like GET /locales/resources.json?lng=__proto__&ns=isAdmin wrote into Object.prototype.
missingKeyHandler — iterated the incoming request body with for...in, which traverses inherited prototype-chain properties. A POST body of the shape {"__proto__": {"isAdmin": true}} was forwarded into i18next.services.backendConnector.saveMissing.
Impact
After a single unauthenticated request of the form GET /locales/resources.json?lng=__proto__&ns=isAdmin, every {} created subsequently in the Node.js process inherits a polluted isAdmin property. This can:
- Break authorisation checks (
if (user.isAdmin) returning true for any user).
- Cause denial of service via type confusion in downstream code reading unexpected prototype-chain properties.
- Be chained into RCE depending on what downstream code reads from polluted objects.
The missingKeyHandler path has the same impact via a different attacker-controlled input (JSON request body instead of query string).
Affected versions
< 3.9.3.
Patch
Fixed in 3.9.3. The patch:
- Blocks
__proto__, constructor, and prototype keys in utils.setPath — both at intermediate path segments (which previously created child objects under Object.prototype) and at the terminal assignment.
- Replaces the
for...in body iteration in missingKeyHandler with Object.keys() plus an explicit dangerous-keys guard, so request-body keys that walk the prototype chain are no longer forwarded.
Workarounds
No workaround short of upgrading. Front-proxying the middleware with a WAF rule that rejects requests containing __proto__, constructor, or prototype in lng / ns query parameters or body keys is a partial mitigation.
Related advisories fixed in the same release
- GHSA-c3h8-g69v-pjrg — HTTP response splitting + XSS-filter bypass (CVE-2026-41683). Same release.
- A separate advisory for path traversal / SSRF via
lng / ns in getResourcesHandler reaching the configured backend connector is filed alongside this one — split out per CNA rules because it is an independently fixable vulnerability with its own attack shape.
Credits
Discovered via an internal security audit of the i18next ecosystem.
References
Summary
Versions of
i18next-http-middlewareprior to 3.9.3 allow an unauthenticated HTTP client to polluteObject.prototypein the Node.js process hosting the middleware, via two unvalidated entry points that reach internal object-key writes:getResourcesHandler— readslng/nsfrom query parameters or route params and passes them toutils.setPath(resources, [lng, ns], value). ThesetPathhelper walked the key path without guarding against__proto__,constructor, orprototypekeys, so a request likeGET /locales/resources.json?lng=__proto__&ns=isAdminwrote intoObject.prototype.missingKeyHandler— iterated the incoming request body withfor...in, which traverses inherited prototype-chain properties. A POST body of the shape{"__proto__": {"isAdmin": true}}was forwarded intoi18next.services.backendConnector.saveMissing.Impact
After a single unauthenticated request of the form
GET /locales/resources.json?lng=__proto__&ns=isAdmin, every{}created subsequently in the Node.js process inherits a pollutedisAdminproperty. This can:if (user.isAdmin)returning true for any user).The
missingKeyHandlerpath has the same impact via a different attacker-controlled input (JSON request body instead of query string).Affected versions
< 3.9.3.Patch
Fixed in 3.9.3. The patch:
__proto__,constructor, andprototypekeys inutils.setPath— both at intermediate path segments (which previously created child objects underObject.prototype) and at the terminal assignment.for...inbody iteration inmissingKeyHandlerwithObject.keys()plus an explicit dangerous-keys guard, so request-body keys that walk the prototype chain are no longer forwarded.Workarounds
No workaround short of upgrading. Front-proxying the middleware with a WAF rule that rejects requests containing
__proto__,constructor, orprototypeinlng/nsquery parameters or body keys is a partial mitigation.Related advisories fixed in the same release
lng/nsingetResourcesHandlerreaching the configured backend connector is filed alongside this one — split out per CNA rules because it is an independently fixable vulnerability with its own attack shape.Credits
Discovered via an internal security audit of the i18next ecosystem.
References