i18next-http-middleware: HTTP response splitting and DoS via unsanitised Content-Language header
Date: 2026-04
Affected: npm/i18next-http-middleware
Attack vector: xss
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-41683
CWE: CWE-113
CWE-79
CVSS: 8.6 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:L)

### Summary Versions of `i18next-http-middleware` prior to 3.9.3 wrote user-controlled language values into the `Content-Language` response header after passing them through `utils.escape()`, which is an HTML-entity encoder that does not strip carriage return, line feed, or other control characters. When the application used an older `i18next` (< 19.5.0) that still exercised the backward-compatibility fallback at `LanguageDetector.js:100` or otherwise produced a raw detected value, CRLF sequences in the attacker-controlled `lng` parameter reached `res.setHeader('Content-Language', ...)` verbatim. ### Impact Two concrete outcomes depending on the Node.js version: - **Node.js < 14.6.0 — HTTP response splitting.** An attacker crafting a request like `GET /?lng=en%0d%0aX-Injected%3A+malicious` could inject arbitrary additional HTTP response headers, enabling: - Session fixation via an injected `Set-Cookie` - Cache poisoning (injecting `Location`, `Content-Type`, etc.) - Reflected XSS in controlled response bodies - **Node.js ≥ 14.6.0 — denial of service.** `res.setHeader()` throws `ERR_INVALID_CHAR` when the value contains CRLF. Because the middleware did not catch this error, it propagated as an unhandled exception, returning a 500 response to **all concurrent users sharing that process** (in worker-pool deployments this can knock out a full server instance). The same header-setting code path fires inside the `languageChanged` event listener and again in the main midd


Mitigations:

Architectural layers (MAESTRO):