CVE-2026-48714: i18next-http-middleware Prototype Pollution via Dotted Missing-Key
A bypass in i18next-http-middleware's missing-key guard lets attackers send a crafted translation key like '__proto__.polluted' over HTTP, which downstream backends split and walk directly into Object

The problem
i18next-http-middleware's missingKeyHandler endpoint (POST /locales/add/:lng/:ns) accepts untrusted key names from the request body and checks them against a denylist of literal strings: __proto__, constructor, and prototype. That check, added in 3.9.3, blocked exact matches but not dotted variants like __proto__.polluted.
When i18next-fs-backend (≤ 2.6.5) receives such a key, its writeFile() splits it on the default keySeparator (.) into segments and passes them to the setPath() walker with no segment-level guard. The walker descends through __proto__ and writes the attacker's value directly onto Object.prototype, affecting every subsequent property lookup in the process.
Proof of concept
POST /locales/add/en/translation HTTP/1.1
Host: target.example.com
Content-Type: application/json
{"__proto__.polluted": "pwned"}
# Verify pollution (in the server process after the request):
# console.log(({}).polluted); // => 'pwned'The root cause is a two-stage failure. The middleware guard compared the raw key against a denylist of literal strings, so __proto__.polluted passed through untouched. The downstream backend then split the key on . into ["__proto__", "polluted"] and the setPath() walker (getLastOfPath in lib/utils.js) had no check against unsafe segment names, so it descended through Object.__proto__ and wrote the caller-controlled value there.
The patch in 3.9.7 adds a utils.hasUnsafeKeySegment(key, keySeparator) helper that splits the key using the configured keySeparator before the denylist check, so any segment matching __proto__, constructor, or prototype causes the whole key to be rejected immediately.
The companion fix in i18next-fs-backend 2.6.6 adds the same guard inside getLastOfPath as defence-in-depth.
The fix
Upgrade i18next-http-middleware to 3.9.7 and i18next-fs-backend to 2.6.6. Both fixes are required for full defence-in-depth. If you cannot upgrade immediately: restrict the missingKeyHandler route to authenticated users only, or set saveMissing: false to disable missing-key persistence for untrusted input, or set keySeparator: false in i18next options to prevent segment splitting (this also disables nested translation keys).
Reported by codeswhite.