undici 6.22.0 → 6.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -329,7 +329,13 @@ const headers = await fetch(url, { method: 'HEAD' })
329
329
 
330
330
  The [Fetch Standard](https://fetch.spec.whatwg.org) requires implementations to exclude certain headers from requests and responses. In browser environments, some headers are forbidden so the user agent remains in full control over them. In Undici, these constraints are removed to give more control to the user.
331
331
 
332
- ### `undici.upgrade([url, options]): Promise`
332
+ #### Content-Encoding
333
+
334
+ * https://www.rfc-editor.org/rfc/rfc9110#field.content-encoding
335
+
336
+ Undici limits the number of `Content-Encoding` layers in a response to **5** to prevent resource exhaustion attacks. If a server responds with more than 5 content-encodings (e.g., `Content-Encoding: gzip, gzip, gzip, gzip, gzip, gzip`), the fetch will be rejected with an error. This limit matches the approach taken by [curl](https://curl.se/docs/CVE-2022-32206.html) and [urllib3](https://github.com/advisories/GHSA-gm62-xv2j-4rw9).
337
+
338
+ #### `undici.upgrade([url, options]): Promise`
333
339
 
334
340
  Upgrade to a different protocol. See [MDN - HTTP - Protocol upgrade mechanism](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) for more details.
335
341
 
@@ -2111,8 +2111,6 @@ async function httpNetworkFetch (
2111
2111
  return
2112
2112
  }
2113
2113
 
2114
- /** @type {string[]} */
2115
- let codings = []
2116
2114
  let location = ''
2117
2115
 
2118
2116
  const headersList = new HeadersList()
@@ -2120,12 +2118,6 @@ async function httpNetworkFetch (
2120
2118
  for (let i = 0; i < rawHeaders.length; i += 2) {
2121
2119
  headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString('latin1'), true)
2122
2120
  }
2123
- const contentEncoding = headersList.get('content-encoding', true)
2124
- if (contentEncoding) {
2125
- // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1
2126
- // "All content-coding values are case-insensitive..."
2127
- codings = contentEncoding.toLowerCase().split(',').map((x) => x.trim())
2128
- }
2129
2121
  location = headersList.get('location', true)
2130
2122
 
2131
2123
  this.body = new Readable({ read: resume })
@@ -2136,9 +2128,23 @@ async function httpNetworkFetch (
2136
2128
  redirectStatusSet.has(status)
2137
2129
 
2138
2130
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding
2139
- if (codings.length !== 0 && request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) {
2131
+ if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) {
2132
+ // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1
2133
+ const contentEncoding = headersList.get('content-encoding', true)
2134
+ // "All content-coding values are case-insensitive..."
2135
+ /** @type {string[]} */
2136
+ const codings = contentEncoding ? contentEncoding.toLowerCase().split(',') : []
2137
+
2138
+ // Limit the number of content-encodings to prevent resource exhaustion.
2139
+ // CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206).
2140
+ const maxContentEncodings = 5
2141
+ if (codings.length > maxContentEncodings) {
2142
+ reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`))
2143
+ return true
2144
+ }
2145
+
2140
2146
  for (let i = codings.length - 1; i >= 0; --i) {
2141
- const coding = codings[i]
2147
+ const coding = codings[i].trim()
2142
2148
  // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2
2143
2149
  if (coding === 'x-gzip' || coding === 'gzip') {
2144
2150
  decoders.push(zlib.createGunzip({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "6.22.0",
3
+ "version": "6.23.0",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {