Multiparty Denial of Service via Prototype-Pollution Field Name (CVE-2026-8161)
by Reported to pillarjs/multiparty maintainers (coordinated disclosure) · 2026-07-05
- Severity
- Medium
- CVE
- CVE-2026-8161 / GHSA-qxch-whhj-8956
- Category
- misc
- Affected product
- multiparty (npm package, multipart/form-data parser)
- Affected versions
- multiparty <= 4.2.3 (fixed in 4.3.0)
- Disclosed
- 2026-07-05
- Patch status
- patched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-05 |
| Author / Researcher | Reported to pillarjs/multiparty maintainers (coordinated disclosure) |
| CVE / Advisory | CVE-2026-8161 / GHSA-qxch-whhj-8956 |
| Category | misc |
| Severity | Medium |
| CVSS Score | Not specified in source |
| Status | PoC |
| Tags | multiparty, nodejs, prototype-pollution, denial-of-service, cwe-1321, uncaught-exception, multipart-parser |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | multiparty (npm package, multipart/form-data parser) |
| Versions Affected | multiparty <= 4.2.3 (fixed in 4.3.0) |
| Language / Platform | Node.js |
| Authentication Required | No |
| Network Access Required | Yes (any HTTP service accepting multipart uploads via a vulnerable multiparty version) |
Summary
multiparty@4.2.3 and earlier store parsed multipart field names and files in plain JavaScript objects and rely on ordinary property lookup (fields[name], files[name]) to detect whether a field has been seen before. Because plain-object lookups traverse the prototype chain, a multipart field literally named __proto__ resolves to the inherited Object.prototype value instead of undefined. Since that inherited value is truthy, the parser’s fallback array-initialization is skipped, and a later .push() call on the non-array value throws an uncaught TypeError inside multiparty’s async parsing flow — crashing the Node.js process handling the upload.
Vulnerability Details
Root Cause
Unsafe assumption that fields[name] || (fields[name] = []) and files[name] || (files[name] = []) only ever observe own-properties. Using a field/file name of __proto__ returns the inherited Object.prototype (a truthy, non-array value) instead of undefined, so the array-initialization fallback never runs. A subsequent .push() on that non-array value throws, and the error occurs inside multiparty’s asynchronous parsing flow where normal caller-side try/catch does not intercept it — CWE-1321 (Prototype Pollution) leading to CWE-248 (uncaught exception) / denial of service.
Attack Vector
- Send a multipart/form-data request to any endpoint backed by a vulnerable multiparty (<=4.2.3) instance.
- Craft a form field (or file field) whose
nameis__proto__. - Multiparty’s internal
fields[name]/files[name]lookup resolves toObject.prototypeinstead ofundefined, skipping array creation. - The parser calls
.push()on the non-arrayObject.prototypevalue, throwing an uncaughtTypeErrorthat crashes the Node.js process.
Impact
Remote, unauthenticated denial of service: a single crafted multipart upload can crash any Node.js service that parses uploads with a vulnerable multiparty version.
Environment / Lab Setup
Target: Dockerized lab — vulnerable server (multiparty 4.2.3) behind nginx on localhost:8080
Patched comparison server (multiparty 4.3.0) on localhost:8081
Attacker: Any HTTP client (secdos.py provided)
Proof of Concept
PoC Script
See
secdos.py,docker-compose.yml,mocklab/, andsecdos-burp-reqin this folder.
| |
The vulnerable target (multiparty 4.2.3, localhost:8080) crashes and the script reports [PASS]; the patched target (multiparty 4.3.0, localhost:8081) handles the request safely and the script reports [FAIL]. If re-running against the vulnerable server, restart the container first.
Detection & Indicators of Compromise
Signs of compromise:
- Application logs showing an uncaught
TypeError: ... push is not a function(or similar) coinciding with an incoming multipart upload. - Repeated process restarts/crash-loops correlated with multipart POST requests.
- Multipart bodies containing a
Content-Disposition: form-data; name="__proto__"part.
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade multiparty to 4.3.0 or later, which uses Object.prototype.hasOwnProperty.call() to validate field ownership before array operations |
| Interim mitigation | Reject multipart field/file names of __proto__, constructor, or prototype at the application/WAF layer before parsing |
References
Notes
Mirrored from https://github.com/Ser0n-ath/CVE-2026-8161 on 2026-07-05. Includes the author’s Docker-based mocklab (vulnerable vs. patched comparison environment) and a sample Burp request.
| |