Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,16 @@ The `body` mixins are the most common way to format the request/response body. M
> The body returned from `undici.request` does not implement `.formData()`.

> [!WARNING]
> Calling `body.formData()` on a fetch response causes undici to buffer and parse the entire body. Since this is dictated by the spec, `body.formData()` must only be called on responses from trusted servers.
> The body mixins `.arrayBuffer()`, `.blob()`, `.bytes()`, `.json()`, `.text()`,
> and `.formData()` buffer the entire body in memory before returning. Where
> applicable, they also decode or parse the payload and retain that
> representation in memory. Calling these methods therefore means trusting that
> the response body is small enough to fit in the available memory. Do not use
> them for responses from untrusted or user-controlled sources. Instead, consume
> the response body as a stream and enforce an application-specific size limit:
> use `response.body` for fetch responses or the `body` returned by
> `undici.request()`. For streaming decoded text, use `body.textStream()` on a
> fetch `Request` or `Response`.

Example usage:

Expand Down
30 changes: 20 additions & 10 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,26 @@ lead to a loss of confidentiality, integrity, or availability.
resources, that is not considered a vulnerability. Applications are
responsible for setting appropriate limits on response sizes.

#### Calling `body.formData()` on untrusted responses

* `body.formData()` buffers and parses the entire response body. Multipart
parsing has inherent security risks, especially when the body is supplied by
an untrusted or user-controlled server. Applications must only call
`body.formData()` on responses from trusted servers. For untrusted responses,
applications should use a dedicated streaming multipart parser and enforce
application-specific limits. Resource exhaustion or parser exposure caused by
calling `body.formData()` on untrusted responses is considered an application
responsibility, not a vulnerability in undici.
#### Calling body-consuming methods on untrusted responses

* The `body.arrayBuffer()`, `body.blob()`, `body.bytes()`, `body.formData()`,
`body.json()`, and `body.text()` methods buffer the entire response body in
memory before returning. Where applicable, they also decode or parse the
payload and retain that representation in memory. Calling one of these
methods means the application trusts that the response is small enough to
fit in the available memory. Applications must not use these methods on
responses from untrusted or user-controlled servers. They should instead
process the response with a streaming API, such as `Response.body`,
`body.textStream()`, or the `Readable` body returned by `undici.request()`,
and enforce application-specific size limits while streaming. Resource
exhaustion caused by buffering an untrusted response is considered an
application responsibility, not a vulnerability in undici.

* Multipart parsing has additional inherent security risks. Applications
processing untrusted multipart responses should use a dedicated streaming
multipart parser and enforce application-specific limits. Parser exposure
caused by calling `body.formData()` on an untrusted response is considered an
application responsibility, not a vulnerability in undici.

#### HTTP/1.1 keep-alive with untrusted servers

Expand Down
9 changes: 9 additions & 0 deletions docs/docs/api/Dispatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,15 @@ example, calling `text()` after `json()` throws a `TypeError`. The body also
provides `dump({ limit })`, which discards up to `limit` bytes (default
`131072`) without destroying the socket.

> [!WARNING]
> The `arrayBuffer()`, `blob()`, `bytes()`, `json()`, and `text()` methods buffer
> the entire body in memory before returning. Where applicable, they also decode
> or parse the payload and retain that representation in memory. Calling these
> methods therefore means trusting that the body is small enough to fit in the
> available memory. Do not use them for bodies received from untrusted or
> user-controlled sources. Instead, process `body` as a `Readable` stream and
> enforce an application-specific size limit.

The body is always a `Readable`, even when empty. Deserializing an empty body
with `json()` throws. To guard against this, verify the status code is not `204`
and the `content-type` header starts with `application/json` before calling
Expand Down
10 changes: 10 additions & 0 deletions docs/docs/api/Fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,16 @@ properties for reading a body. Each consuming method reads the body once; after
the body has been consumed, [`bodyUsed`](#bodybodyused) becomes `true` and
calling another consuming method throws a `TypeError`.

> [!WARNING]
> The `arrayBuffer()`, `blob()`, `bytes()`, `formData()`, `json()`, and `text()`
> methods buffer the entire body in memory before returning. Where applicable,
> they also decode or parse the payload and retain that representation in
> memory. Calling these methods therefore means trusting that the body is small
> enough to fit in the available memory. Do not use them for bodies received
> from untrusted or user-controlled sources. Instead, process `body.body` or
> `body.textStream()` incrementally and enforce an application-specific size
> limit.

### `body.arrayBuffer()`

<!-- YAML
Expand Down
11 changes: 10 additions & 1 deletion docs/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,16 @@ The `body` mixins are the most common way to format the request/response body. M
> The body returned from `undici.request` does not implement `.formData()`.

> [!WARNING]
> Calling `body.formData()` on a fetch response causes undici to buffer and parse the entire body. Since this is dictated by the spec, `body.formData()` must only be called on responses from trusted servers.
> The body mixins `.arrayBuffer()`, `.blob()`, `.bytes()`, `.json()`, `.text()`,
> and `.formData()` buffer the entire body in memory before returning. Where
> applicable, they also decode or parse the payload and retain that
> representation in memory. Calling these methods therefore means trusting that
> the response body is small enough to fit in the available memory. Do not use
> them for responses from untrusted or user-controlled sources. Instead, consume
> the response body as a stream and enforce an application-specific size limit:
> use `response.body` for fetch responses or the `body` returned by
> `undici.request()`. For streaming decoded text, use `body.textStream()` on a
> fetch `Request` or `Response`.

Example usage:

Expand Down
Loading