@zuplo/cli 6.70.71 → 6.71.1

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.
Files changed (79) hide show
  1. package/node_modules/@fastify/reply-from/node_modules/undici/docs/docs/api/Client.md +3 -0
  2. package/node_modules/@fastify/reply-from/node_modules/undici/docs/docs/api/Cookies.md +27 -0
  3. package/node_modules/@fastify/reply-from/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +1 -0
  4. package/node_modules/@fastify/reply-from/node_modules/undici/lib/core/socks5-client.js +14 -4
  5. package/node_modules/@fastify/reply-from/node_modules/undici/lib/core/socks5-utils.js +18 -4
  6. package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/agent.js +1 -1
  7. package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/balanced-pool.js +1 -1
  8. package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/client-h1.js +69 -1
  9. package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/client.js +3 -2
  10. package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/dispatcher-base.js +19 -0
  11. package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/pool.js +1 -1
  12. package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/proxy-agent.js +2 -1
  13. package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +45 -34
  14. package/node_modules/@fastify/reply-from/node_modules/undici/lib/util/cache.js +8 -2
  15. package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/cookies/parse.js +17 -25
  16. package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/websocket/permessage-deflate.js +13 -31
  17. package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/websocket/receiver.js +80 -23
  18. package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -1
  19. package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/websocket/websocket.js +8 -1
  20. package/node_modules/@fastify/reply-from/node_modules/undici/package.json +1 -1
  21. package/node_modules/@fastify/reply-from/node_modules/undici/types/client.d.ts +16 -0
  22. package/node_modules/@zuplo/core/package.json +1 -1
  23. package/node_modules/@zuplo/graphql/package.json +1 -1
  24. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  25. package/node_modules/@zuplo/otel/package.json +1 -1
  26. package/node_modules/@zuplo/runtime/package.json +1 -1
  27. package/node_modules/axios/CHANGELOG.md +52 -1
  28. package/node_modules/axios/README.md +30 -2
  29. package/node_modules/axios/dist/axios.js +350 -134
  30. package/node_modules/axios/dist/axios.min.js +3 -3
  31. package/node_modules/axios/dist/axios.min.js.map +1 -1
  32. package/node_modules/axios/dist/browser/axios.cjs +355 -90
  33. package/node_modules/axios/dist/esm/axios.js +355 -90
  34. package/node_modules/axios/dist/esm/axios.min.js +2 -2
  35. package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  36. package/node_modules/axios/dist/node/axios.cjs +399 -104
  37. package/node_modules/axios/index.d.cts +2 -0
  38. package/node_modules/axios/index.d.ts +2 -0
  39. package/node_modules/axios/lib/adapters/fetch.js +113 -37
  40. package/node_modules/axios/lib/adapters/http.js +132 -43
  41. package/node_modules/axios/lib/core/Axios.js +3 -2
  42. package/node_modules/axios/lib/core/AxiosHeaders.js +10 -7
  43. package/node_modules/axios/lib/core/buildFullPath.js +29 -1
  44. package/node_modules/axios/lib/core/mergeConfig.js +34 -0
  45. package/node_modules/axios/lib/defaults/transitional.js +1 -0
  46. package/node_modules/axios/lib/env/data.js +1 -1
  47. package/node_modules/axios/lib/helpers/buildURL.js +5 -3
  48. package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +16 -11
  49. package/node_modules/axios/lib/helpers/formDataToJSON.js +25 -3
  50. package/node_modules/axios/lib/helpers/resolveConfig.js +5 -3
  51. package/node_modules/axios/lib/helpers/shouldBypassProxy.js +33 -1
  52. package/node_modules/axios/lib/helpers/toFormData.js +40 -10
  53. package/node_modules/axios/lib/utils.js +75 -11
  54. package/node_modules/axios/package.json +1 -1
  55. package/node_modules/body-parser/README.md +16 -1
  56. package/node_modules/body-parser/index.js +4 -20
  57. package/node_modules/body-parser/lib/read.js +17 -17
  58. package/node_modules/body-parser/lib/types/json.js +60 -32
  59. package/node_modules/body-parser/lib/types/raw.js +3 -3
  60. package/node_modules/body-parser/lib/types/text.js +3 -3
  61. package/node_modules/body-parser/lib/types/urlencoded.js +16 -20
  62. package/node_modules/body-parser/lib/utils.js +18 -16
  63. package/node_modules/body-parser/node_modules/content-type/LICENSE +22 -0
  64. package/node_modules/body-parser/node_modules/content-type/README.md +69 -0
  65. package/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +26 -0
  66. package/node_modules/body-parser/node_modules/content-type/dist/index.js +170 -0
  67. package/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -0
  68. package/node_modules/body-parser/node_modules/content-type/package.json +52 -0
  69. package/node_modules/body-parser/node_modules/http-errors/HISTORY.md +186 -0
  70. package/node_modules/body-parser/node_modules/http-errors/LICENSE +23 -0
  71. package/node_modules/body-parser/node_modules/http-errors/README.md +169 -0
  72. package/node_modules/body-parser/node_modules/http-errors/index.js +290 -0
  73. package/node_modules/body-parser/node_modules/http-errors/package.json +54 -0
  74. package/node_modules/body-parser/package.json +23 -10
  75. package/node_modules/form-data/CHANGELOG.md +29 -2
  76. package/node_modules/form-data/README.md +4 -4
  77. package/node_modules/form-data/lib/form_data.js +14 -2
  78. package/node_modules/form-data/package.json +7 -7
  79. package/package.json +6 -6
@@ -8,40 +8,35 @@ const tail = Buffer.from([0x00, 0x00, 0xff, 0xff])
8
8
  const kBuffer = Symbol('kBuffer')
9
9
  const kLength = Symbol('kLength')
10
10
 
11
- // Default maximum decompressed message size: 4 MB
12
- const kDefaultMaxDecompressedSize = 4 * 1024 * 1024
13
-
14
11
  class PerMessageDeflate {
15
12
  /** @type {import('node:zlib').InflateRaw} */
16
13
  #inflate
17
14
 
18
15
  #options = {}
19
16
 
20
- /** @type {boolean} */
21
- #aborted = false
22
-
23
- /** @type {Function|null} */
24
- #currentCallback = null
17
+ #maxPayloadSize = 0
25
18
 
26
19
  /**
27
20
  * @param {Map<string, string>} extensions
28
21
  */
29
- constructor (extensions) {
22
+ constructor (extensions, options) {
30
23
  this.#options.serverNoContextTakeover = extensions.has('server_no_context_takeover')
31
24
  this.#options.serverMaxWindowBits = extensions.get('server_max_window_bits')
25
+
26
+ this.#maxPayloadSize = options.maxPayloadSize
32
27
  }
33
28
 
29
+ /**
30
+ * Decompress a compressed payload.
31
+ * @param {Buffer} chunk Compressed data
32
+ * @param {boolean} fin Final fragment flag
33
+ * @param {Function} callback Callback function
34
+ */
34
35
  decompress (chunk, fin, callback) {
35
36
  // An endpoint uses the following algorithm to decompress a message.
36
37
  // 1. Append 4 octets of 0x00 0x00 0xff 0xff to the tail end of the
37
38
  // payload of the message.
38
39
  // 2. Decompress the resulting data using DEFLATE.
39
-
40
- if (this.#aborted) {
41
- callback(new MessageSizeExceededError())
42
- return
43
- }
44
-
45
40
  if (!this.#inflate) {
46
41
  let windowBits = Z_DEFAULT_WINDOWBITS
47
42
 
@@ -64,23 +59,12 @@ class PerMessageDeflate {
64
59
  this.#inflate[kLength] = 0
65
60
 
66
61
  this.#inflate.on('data', (data) => {
67
- if (this.#aborted) {
68
- return
69
- }
70
-
71
62
  this.#inflate[kLength] += data.length
72
63
 
73
- if (this.#inflate[kLength] > kDefaultMaxDecompressedSize) {
74
- this.#aborted = true
64
+ if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) {
65
+ callback(new MessageSizeExceededError())
75
66
  this.#inflate.removeAllListeners()
76
- this.#inflate.destroy()
77
67
  this.#inflate = null
78
-
79
- if (this.#currentCallback) {
80
- const cb = this.#currentCallback
81
- this.#currentCallback = null
82
- cb(new MessageSizeExceededError())
83
- }
84
68
  return
85
69
  }
86
70
 
@@ -93,14 +77,13 @@ class PerMessageDeflate {
93
77
  })
94
78
  }
95
79
 
96
- this.#currentCallback = callback
97
80
  this.#inflate.write(chunk)
98
81
  if (fin) {
99
82
  this.#inflate.write(tail)
100
83
  }
101
84
 
102
85
  this.#inflate.flush(() => {
103
- if (this.#aborted || !this.#inflate) {
86
+ if (!this.#inflate) {
104
87
  return
105
88
  }
106
89
 
@@ -108,7 +91,6 @@ class PerMessageDeflate {
108
91
 
109
92
  this.#inflate[kBuffer].length = 0
110
93
  this.#inflate[kLength] = 0
111
- this.#currentCallback = null
112
94
 
113
95
  callback(null, full)
114
96
  })
@@ -39,18 +39,27 @@ class ByteParser extends Writable {
39
39
  /** @type {import('./websocket').Handler} */
40
40
  #handler
41
41
 
42
+ /** @type {number} */
43
+ #maxFragments
44
+
45
+ /** @type {number} */
46
+ #maxPayloadSize
47
+
42
48
  /**
43
49
  * @param {import('./websocket').Handler} handler
44
50
  * @param {Map<string, string>|null} extensions
51
+ * @param {{ maxFragments?: number, maxPayloadSize?: number }} [options]
45
52
  */
46
- constructor (handler, extensions) {
53
+ constructor (handler, extensions, options = {}) {
47
54
  super()
48
55
 
49
56
  this.#handler = handler
50
57
  this.#extensions = extensions == null ? new Map() : extensions
58
+ this.#maxFragments = options.maxFragments ?? 0
59
+ this.#maxPayloadSize = options.maxPayloadSize ?? 0
51
60
 
52
61
  if (this.#extensions.has('permessage-deflate')) {
53
- this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions))
62
+ this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions, options))
54
63
  }
55
64
  }
56
65
 
@@ -66,6 +75,19 @@ class ByteParser extends Writable {
66
75
  this.run(callback)
67
76
  }
68
77
 
78
+ #validatePayloadLength () {
79
+ if (
80
+ this.#maxPayloadSize > 0 &&
81
+ !isControlFrame(this.#info.opcode) &&
82
+ this.#info.payloadLength + this.#fragmentsBytes > this.#maxPayloadSize
83
+ ) {
84
+ failWebsocketConnection(this.#handler, 1009, 'Payload size exceeds maximum allowed size')
85
+ return false
86
+ }
87
+
88
+ return true
89
+ }
90
+
69
91
  /**
70
92
  * Runs whenever a new chunk is received.
71
93
  * Callback is called whenever there are no more chunks buffering,
@@ -154,6 +176,10 @@ class ByteParser extends Writable {
154
176
  if (payloadLength <= 125) {
155
177
  this.#info.payloadLength = payloadLength
156
178
  this.#state = parserStates.READ_DATA
179
+
180
+ if (!this.#validatePayloadLength()) {
181
+ return
182
+ }
157
183
  } else if (payloadLength === 126) {
158
184
  this.#state = parserStates.PAYLOADLENGTH_16
159
185
  } else if (payloadLength === 127) {
@@ -178,6 +204,10 @@ class ByteParser extends Writable {
178
204
 
179
205
  this.#info.payloadLength = buffer.readUInt16BE(0)
180
206
  this.#state = parserStates.READ_DATA
207
+
208
+ if (!this.#validatePayloadLength()) {
209
+ return
210
+ }
181
211
  } else if (this.#state === parserStates.PAYLOADLENGTH_64) {
182
212
  if (this.#byteOffset < 8) {
183
213
  return callback()
@@ -200,6 +230,10 @@ class ByteParser extends Writable {
200
230
 
201
231
  this.#info.payloadLength = lower
202
232
  this.#state = parserStates.READ_DATA
233
+
234
+ if (!this.#validatePayloadLength()) {
235
+ return
236
+ }
203
237
  } else if (this.#state === parserStates.READ_DATA) {
204
238
  if (this.#byteOffset < this.#info.payloadLength) {
205
239
  return callback()
@@ -212,7 +246,9 @@ class ByteParser extends Writable {
212
246
  this.#state = parserStates.INFO
213
247
  } else {
214
248
  if (!this.#info.compressed) {
215
- this.writeFragments(body)
249
+ if (!this.writeFragments(body)) {
250
+ return
251
+ }
216
252
 
217
253
  // If the frame is not fragmented, a message has been received.
218
254
  // If the frame is fragmented, it will terminate with a fin bit set
@@ -224,29 +260,41 @@ class ByteParser extends Writable {
224
260
 
225
261
  this.#state = parserStates.INFO
226
262
  } else {
227
- this.#extensions.get('permessage-deflate').decompress(body, this.#info.fin, (error, data) => {
228
- if (error) {
229
- // Use 1009 (Message Too Big) for decompression size limit errors
230
- const code = error instanceof MessageSizeExceededError ? 1009 : 1007
231
- failWebsocketConnection(this.#handler, code, error.message)
232
- return
233
- }
234
-
235
- this.writeFragments(data)
263
+ this.#extensions.get('permessage-deflate').decompress(
264
+ body,
265
+ this.#info.fin,
266
+ (error, data) => {
267
+ if (error) {
268
+ const code = error instanceof MessageSizeExceededError ? 1009 : 1007
269
+ failWebsocketConnection(this.#handler, code, error.message)
270
+ return
271
+ }
272
+
273
+ if (!this.writeFragments(data)) {
274
+ return
275
+ }
276
+
277
+ // Check cumulative fragment size
278
+ if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) {
279
+ failWebsocketConnection(this.#handler, 1009, new MessageSizeExceededError().message)
280
+ return
281
+ }
282
+
283
+ if (!this.#info.fin) {
284
+ this.#state = parserStates.INFO
285
+ this.#loop = true
286
+ this.run(callback)
287
+ return
288
+ }
289
+
290
+ websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments())
236
291
 
237
- if (!this.#info.fin) {
238
- this.#state = parserStates.INFO
239
292
  this.#loop = true
293
+ this.#state = parserStates.INFO
240
294
  this.run(callback)
241
- return
242
- }
243
-
244
- websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments())
245
-
246
- this.#loop = true
247
- this.#state = parserStates.INFO
248
- this.run(callback)
249
- })
295
+ },
296
+ this.#fragmentsBytes
297
+ )
250
298
 
251
299
  this.#loop = false
252
300
  break
@@ -305,8 +353,17 @@ class ByteParser extends Writable {
305
353
  }
306
354
 
307
355
  writeFragments (fragment) {
356
+ if (
357
+ this.#maxFragments > 0 &&
358
+ this.#fragments.length === this.#maxFragments
359
+ ) {
360
+ failWebsocketConnection(this.#handler, 1008, 'Too many message fragments')
361
+ return false
362
+ }
363
+
308
364
  this.#fragmentsBytes += fragment.length
309
365
  this.#fragments.push(fragment)
366
+ return true
310
367
  }
311
368
 
312
369
  consumeFragments () {
@@ -258,7 +258,14 @@ class WebSocketStream {
258
258
  #onConnectionEstablished (response, parsedExtensions) {
259
259
  this.#handler.socket = response.socket
260
260
 
261
- const parser = new ByteParser(this.#handler, parsedExtensions)
261
+ // Get options from dispatcher options
262
+ const maxFragments = this.#handler.controller.dispatcher?.webSocketOptions?.maxFragments
263
+ const maxPayloadSize = this.#handler.controller.dispatcher?.webSocketOptions?.maxPayloadSize
264
+
265
+ const parser = new ByteParser(this.#handler, parsedExtensions, {
266
+ maxFragments,
267
+ maxPayloadSize
268
+ })
262
269
  parser.on('drain', () => this.#handler.onParserDrain())
263
270
  parser.on('error', (err) => this.#handler.onParserError(err))
264
271
 
@@ -468,7 +468,14 @@ class WebSocket extends EventTarget {
468
468
  // once this happens, the connection is open
469
469
  this.#handler.socket = response.socket
470
470
 
471
- const parser = new ByteParser(this.#handler, parsedExtensions)
471
+ const webSocketOptions = this.#handler.controller.dispatcher?.webSocketOptions
472
+ const maxFragments = webSocketOptions?.maxFragments
473
+ const maxPayloadSize = webSocketOptions?.maxPayloadSize
474
+
475
+ const parser = new ByteParser(this.#handler, parsedExtensions, {
476
+ maxFragments,
477
+ maxPayloadSize
478
+ })
472
479
  parser.on('drain', () => this.#handler.onParserDrain())
473
480
  parser.on('error', (err) => this.#handler.onParserError(err))
474
481
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "7.27.2",
3
+ "version": "7.28.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": {
@@ -107,6 +107,8 @@ export declare namespace Client {
107
107
  * @default 60000
108
108
  */
109
109
  pingInterval?: number;
110
+ /** WebSocket-specific configuration options. */
111
+ webSocket?: WebSocketOptions;
110
112
  }
111
113
  export interface SocketInfo {
112
114
  localAddress?: string
@@ -118,6 +120,20 @@ export declare namespace Client {
118
120
  bytesWritten?: number
119
121
  bytesRead?: number
120
122
  }
123
+ export interface WebSocketOptions {
124
+ /**
125
+ * Maximum number of fragments in a message. Set to 0 to disable the limit.
126
+ * @default 131072
127
+ */
128
+ maxFragments?: number;
129
+ /**
130
+ * Maximum allowed payload size in bytes for WebSocket messages.
131
+ * Applied to uncompressed messages, compressed frame payloads, and decompressed (permessage-deflate) messages.
132
+ * Set to 0 to disable the limit.
133
+ * @default 134217728 (128 MB)
134
+ */
135
+ maxPayloadSize?: number;
136
+ }
121
137
  }
122
138
 
123
139
  export default Client
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuplo/core",
3
- "version": "6.70.71",
3
+ "version": "6.71.1",
4
4
  "repository": "https://github.com/zuplo/zuplo",
5
5
  "author": "Zuplo, Inc.",
6
6
  "type": "module",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zuplo/graphql",
3
3
  "type": "module",
4
- "version": "6.70.71",
4
+ "version": "6.71.1",
5
5
  "repository": "https://github.com/zuplo/zuplo",
6
6
  "author": "Zuplo, Inc.",
7
7
  "exports": {
@@ -2,7 +2,7 @@
2
2
  "name": "@zuplo/openapi-tools",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "6.70.71",
5
+ "version": "6.71.1",
6
6
  "description": "Tooling for OpenAPI files",
7
7
  "repository": {
8
8
  "type": "git",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zuplo/otel",
3
3
  "type": "module",
4
- "version": "6.70.71",
4
+ "version": "6.71.1",
5
5
  "repository": "https://github.com/zuplo/zuplo",
6
6
  "author": "Zuplo, Inc.",
7
7
  "exports": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zuplo/runtime",
3
3
  "type": "module",
4
- "version": "6.70.71",
4
+ "version": "6.71.1",
5
5
  "repository": "https://github.com/zuplo/zuplo",
6
6
  "author": "Zuplo, Inc.",
7
7
  "exports": {
@@ -1,5 +1,56 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.17.0 — June 1, 2026
4
+
5
+ This release adds Node HTTP zstd decompression, hardens config and release workflows, and fixes authentication, header, proxy, and type-handling regressions.
6
+
7
+ ## 🔒 Security Fixes
8
+
9
+ * **Config Hardening:** Guarded `socketPath`, `params`, and `paramsSerializer` reads with own-property checks to prevent inherited prototype values from affecting request behavior, including SSRF-sensitive paths. (__#10901__, __#10922__)
10
+ * **Release Publishing:** Switched the publish workflow to npm staged publishing for safer, auditable package releases with provenance. (__#10926__)
11
+
12
+ ## 🚀 New Features
13
+
14
+ * **HTTP Compression:** Added Node HTTP adapter support for zstd response decompression, with `transitional.advertiseZstdAcceptEncoding` controlling whether `zstd` is advertised in `Accept-Encoding`. (__#6792__, __#10920__)
15
+
16
+ ## 🐛 Bug Fixes
17
+
18
+ * **Authentication Handling:** Restored Basic auth on same-origin Node redirects while continuing to strip credentials cross-origin, and aligned the fetch adapter with HTTP adapter behavior for URL-embedded Basic auth. (__#10929__, __#10896__)
19
+ * **Proxy TLS:** Preserved user `httpsAgent` TLS options when tunneling HTTPS requests through HTTP CONNECT proxies. (__#10957__)
20
+ * **React Native FormData:** Cleared default `Content-Type` for React Native `FormData` so multipart boundaries can be generated correctly. (__#10898__)
21
+ * **Headers:** Silently skipped empty or whitespace-only header names instead of throwing, matching parsed-header behavior and avoiding React Native response crashes. (__#10875__)
22
+ * **Request Data Merging:** Preserved enumerable symbol keys when cloning plain request data through axios merge logic. (__#10812__)
23
+ * **Bundler Compatibility:** Converted `resolveConfig` from an arrow default export to a named function export to avoid webpack and Babel transform interop failures. (__#10891__)
24
+ * **Types:** Corrected `AxiosHeaders.toJSON()` return types and updated CommonJS `isCancel` typings to narrow to `CanceledError<T>`. (__#10956__, __#10952__)
25
+ * **Build Tooling:** Avoided emitting a null `Authorization` header from the GitHub build helper when `GITHUB_TOKEN` is unset. (__#10931__)
26
+
27
+ ## 🔧 Maintenance & Chores
28
+
29
+ * **HTTP/2 Internals:** Extracted `Http2Sessions` into its own helper module and added direct unit coverage for session pooling, timeout, and cleanup behavior. (__#10861__)
30
+ * **Package Publishing:** Reduced published package size by switching to a `files` allowlist and dropping unneeded unminified bundle source maps. (__#10939__)
31
+ * **CI and Release Automation:** Added bundle-size reporting, moved reports to the job summary, fixed bundle-size comparison coverage, added Node 26 to the matrix, pinned npm for staged publishing, and prepared the 1.17.0 release. (__#10907__, __#10911__, __#10916__, __#10927__, __#10935__, __#10983__)
32
+ * **Developer Workflow:** Added a dev container and iterated on OpenSpec workflow files before removing them from the release branch. (__#10925__, __#10914__, __#10958__)
33
+ * **Documentation and Policy:** Updated disclosure, contributor, collaboration, threat-model, advanced docs, README badges, release notes, moderator configuration, and project metadata. (__#10890__, __#10889__, __#10921__, __#10945__, __#10905__, __#10933__, __#10915__, __#10887__, __#10955__)
34
+ * **Dependencies:** Bumped Babel tooling, Commitlint, ESLint, Rollup, Globals, Vitest, Playwright, `fs-extra`, `qs`, docs dependencies, and GitHub Actions dependencies including `actions/dependency-review-action` and `zizmorcore/zizmor-action`. (__#10871__, __#10879__, __#10918__, __#10919__, __#10934__, __#10947__, __#10954__, __#10960__)
35
+
36
+ ## 🌟 New Contributors
37
+
38
+ We are thrilled to welcome our new contributors. Thank you for helping improve axios:
39
+
40
+ * __@BasixKOR__ (__#6792__)
41
+ * __@carladams1299-lab__ (__#10861__)
42
+ * __@LaplaceYoung__ (__#10812__)
43
+ * __@JamieMagee__ (__#10939__)
44
+ * __@RonGamzu__ (__#10905__)
45
+ * __@sapirbaruch__ (__#10891__)
46
+ * __@nezukoagent__ (__#10901__)
47
+ * __@devareddy05__ (__#10929__)
48
+ * __@Mohammad-Faiz-Cloud-Engineer__ (__#10922__)
49
+ * __@azandabot__ (__#10931__)
50
+ * __@niksy__ (__#10896__)
51
+
52
+ [Full Changelog](https://github.com/axios/axios/compare/v1.16.1...v1.17.0)
53
+
3
54
  ## v1.16.1 — May 13, 2026
4
55
 
5
56
  This release ships a defence-in-depth fix for prototype pollution in `formDataToJSON`, hardens proxy and CI workflows, restores Webpack 4 compatibility for the fetch adapter, and includes several small bug fixes and maintenance improvements.
@@ -1432,7 +1483,7 @@ This functionality is considered as a fix.
1432
1483
 
1433
1484
  - fix: improve AxiosHeaders class [#5224](https://github.com/axios/axios/pull/5224)
1434
1485
  - fix: TypeScript type definitions for commonjs [#5196](https://github.com/axios/axios/pull/5196)
1435
- - fix: type definition of use method on AxiosInterceptorManager to match the the README [#5071](https://github.com/axios/axios/pull/5071)
1486
+ - fix: type definition of use method on AxiosInterceptorManager to match the README [#5071](https://github.com/axios/axios/pull/5071)
1436
1487
  - fix: \_\_dirname is not defined in the sandbox [#5269](https://github.com/axios/axios/pull/5269)
1437
1488
  - fix: AxiosError.toJSON method to avoid circular references [#5247](https://github.com/axios/axios/pull/5247)
1438
1489
  - fix: Z_BUF_ERROR when content-encoding is set but the response body is empty [#5250](https://github.com/axios/axios/pull/5250)
@@ -773,6 +773,7 @@ These config options are available for requests. Only `url` is required. Request
773
773
  // When no `transformRequest` is set, it must be of one of the following types:
774
774
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
775
775
  // - Browser only: FormData, File, Blob
776
+ // - React Native: FormData
776
777
  // - Node only: Stream, Buffer, FormData (form-data package)
777
778
  data: {
778
779
  firstName: 'Fred'
@@ -877,10 +878,12 @@ These config options are available for requests. Only `url` is required. Request
877
878
  // Do whatever you want with the Axios progress event
878
879
  },
879
880
 
880
- // `maxContentLength` defines the max size of the http response content in bytes allowed in node.js
881
+ // `maxContentLength` defines the max size of the response content in bytes.
882
+ // It is enforced by the Node.js HTTP adapter and the fetch adapter.
881
883
  maxContentLength: 2000,
882
884
 
883
- // `maxBodyLength` (Node only option) defines the max size of the http request content in bytes allowed
885
+ // `maxBodyLength` defines the max size of the request content in bytes.
886
+ // It is enforced by the Node.js HTTP adapter and the fetch adapter when the body length can be determined.
884
887
  maxBodyLength: 2000,
885
888
 
886
889
  // `redact` masks matching config keys when AxiosError#toJSON() is called.
@@ -898,6 +901,12 @@ These config options are available for requests. Only `url` is required. Request
898
901
  // If set to 0, Axios follows no redirects.
899
902
  maxRedirects: 21, // default
900
903
 
904
+ // `sensitiveHeaders` (Node only option) lists custom secret-bearing headers
905
+ // to remove from cross-origin redirects. Matching is case-insensitive.
906
+ // Same-origin redirects keep these headers. If `maxRedirects` is 0, this
907
+ // option is not used.
908
+ sensitiveHeaders: ['X-API-Key'],
909
+
901
910
  // `beforeRedirect` defines a function that Axios calls before redirect.
902
911
  // Use this to adjust the request options upon redirecting,
903
912
  // to inspect the latest response headers,
@@ -1640,6 +1649,7 @@ server = app.listen(3000);
1640
1649
 
1641
1650
  To send data as `multipart/form-data`, pass a FormData instance as the payload.
1642
1651
  You do not need to set the `Content-Type` header. Axios detects it from the payload type.
1652
+ For browser, web worker, and React Native `FormData`, leave `Content-Type` unset so the runtime can add the multipart boundary.
1643
1653
 
1644
1654
  ```js
1645
1655
  const formData = new FormData();
@@ -2068,6 +2078,8 @@ The `rewrite` argument controls the overwriting behavior:
2068
2078
 
2069
2079
  The option can also accept a user-defined function that determines whether to overwrite the value.
2070
2080
 
2081
+ Empty or whitespace-only header names are ignored.
2082
+
2071
2083
  Returns `this`.
2072
2084
 
2073
2085
  ### AxiosHeaders#get(header)
@@ -2243,6 +2255,8 @@ const { data } = fetchAxios.get(url);
2243
2255
  The adapter supports the same features as the `xhr` adapter, including upload and download progress capturing.
2244
2256
  It also supports response types such as `stream` and `formdata` when the environment supports them.
2245
2257
 
2258
+ When `auth` is omitted, the fetch adapter can read HTTP Basic auth credentials from the request URL, for example `https://user:pass@example.com`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated, and `auth` takes precedence over URL-embedded credentials.
2259
+
2246
2260
  ### Custom fetch
2247
2261
 
2248
2262
  Since `v1.12.0`, you can configure the fetch adapter to use a custom fetch API instead of environment globals.
@@ -2365,6 +2379,20 @@ try {
2365
2379
  }
2366
2380
  ```
2367
2381
 
2382
+ Use `axios.isCancel<T>()` to narrow cancellation errors to `CanceledError<T>`:
2383
+
2384
+ ```typescript
2385
+ const controller = new AbortController();
2386
+
2387
+ try {
2388
+ await axios.get<User>('/user?ID=12345', { signal: controller.signal });
2389
+ } catch (error) {
2390
+ if (axios.isCancel<User>(error)) {
2391
+ handleCancellation(error);
2392
+ }
2393
+ }
2394
+ ```
2395
+
2368
2396
  Because axios publishes an ESM default export and a CJS `module.exports`, TypeScript has a few caveats.
2369
2397
  The recommended setting is `"moduleResolution": "node16"`, which is implied by `"module": "node16"`. This requires TypeScript 4.7 or greater.
2370
2398
  If you use ESM, your settings should be fine.