Share
## https://sploitus.com/exploit?id=7F8C557D-0F6C-59B6-881F-A0BC07889065
# CVE-2026-8161
Proof of concept of CVE-2026-8161 (Multiparty)

# Description

`multiparty@4.2.3` and earlier are vulnerable to denial of service through an uncaught exception.

The parser stores uploaded fields and files in plain JavaScript objects and does not safely distinguish parser owned keys from inherited object properties. A crafted multipart field name can cause the parser to read unexpected prototype-chain values and crash while handling the upload.

Any service that accepts multipart uploads through vulnerable versions of multiparty may be affected.

# How it works
The issue happens because `fields` and `files` are plain JavaScript objects, but they are used like safe key-value maps for user-controlled names.


```js
var fieldsArray = fields[name] || (fields[name] = [])
fieldsArray.push(value)

var filesArray = files[name] || (files[name] = [])
filesArray.push(file)
```

The issue is that `fields[name]` and `files[name]` use normal JavaScript property lookup. For plain objects, that lookup can return inherited properties from the prototype chain instead of only values stored on the object itself.

When name is `__proto__`, JavaScript can resolve it through the prototype chain and return the inherited prototype object instead of undefined. Since that value is truthy, the fallback assignment is skipped and the parser never creates a real array for that field.

The patch fixes this by only trusting keys that belong directly to the object:

```js
var filesArray = Object.prototype.hasOwnProperty.call(files, name)
  ? files[name]
  : undefined
```

Then the parser appends only when the stored value is actually an array, otherwise it initializes a fresh one:

```js
if (Array.isArray(filesArray)) {
  filesArray.push(file)
} else {
  files[name] = [file]
}
```

When .push() is called on a value that is not an array, it throws a TypeError. Because this happens inside Multiparty’s async parsing flow, normal caller-side error handling may not catch it, allowing the exception to crash the process.

# Timeline

- 2026-01-12: Vulnerability reported to the multiparty maintainers.
- 2026-01-17: Report accepted, remediation work began.
- 2026-02-14: Coordinated review started with @pillarjs/security-triage.
- 2026-02-16: Patch discussions -> `Object.prototype.hasOwnProperty.call(...)`.
- 2026-03-29: Advisory title and metadata updated to reflect denial-of-service impact.
- 2026-04: Remediation approach reviewed and approved.
- 2026-05-08: Advisory finalized and CVE-2026-8161 reserved.
- 2026-05-11: Fix merged into pillarjs:master.



# Demo Usage

Run the mocklab environment and send the test payload to both targets:

```
docker compose up -d
python3 secdos.py -u http://localhost:8080/api/submit
python3 secdos.py -u http://localhost:8081/api/submit
```

The vulnerable target will crash and return `[PASS]`. The patched target will handle the request safely and return `[FAIL]`.

> If re-running against the vulnerable server, restart it first

# Setup overview

### Vulnerable Server

- Access on localhost:8080
- Nginx server acting as reverse proxy, on failure it displays error page with status 502
- Nginx resolves vuln server address by service name
- Uses multiparty 4.2.3 (vulnerable)


### Patched Server

- Running & Accessed on localhost:8081
- Nginx not required
- Uses multiparty 4.3.0 (patched)

Building a patched image from dockerfile requires a build arg `PATCHED=1`

## References

https://github.com/pillarjs/multiparty/security/advisories/GHSA-qxch-whhj-8956
https://github.com/pillarjs/multiparty/commit/8ee6aca09aca29e923da48da8260c87aa964b282