Bump undici from 6.23.0 to 6.24.0 in the npm_and_yarn group across 1 directory (#432)
559a930 · dependabot[bot] · 2026-03-14 16:57
Message
{commit_body(@commit)}
Files changed
modified
dist/index.js
+135
−16
@@ -26921,6 +26921,24 @@ class SecureProxyConnectionError extends UndiciError {
| 26921 | 26921 | [kSecureProxyConnectionError] = true |
| 26922 | 26922 | } |
| 26923 | 26923 | |
| 26924 | +const kMessageSizeExceededError = Symbol.for('undici.error.UND_ERR_WS_MESSAGE_SIZE_EXCEEDED') | |
| 26925 | +class MessageSizeExceededError extends UndiciError { | |
| 26926 | + constructor (message) { | |
| 26927 | + super(message) | |
| 26928 | + this.name = 'MessageSizeExceededError' | |
| 26929 | + this.message = message || 'Max decompressed message size exceeded' | |
| 26930 | + this.code = 'UND_ERR_WS_MESSAGE_SIZE_EXCEEDED' | |
| 26931 | + } | |
| 26932 | + | |
| 26933 | + static [Symbol.hasInstance] (instance) { | |
| 26934 | + return instance && instance[kMessageSizeExceededError] === true | |
| 26935 | + } | |
| 26936 | + | |
| 26937 | + get [kMessageSizeExceededError] () { | |
| 26938 | + return true | |
| 26939 | + } | |
| 26940 | +} | |
| 26941 | + | |
| 26924 | 26942 | module.exports = { |
| 26925 | 26943 | AbortError, |
| 26926 | 26944 | HTTPParserError, |
@@ -26944,7 +26962,8 @@ module.exports = {
| 26944 | 26962 | ResponseExceededMaxSizeError, |
| 26945 | 26963 | RequestRetryError, |
| 26946 | 26964 | ResponseError, |
| 26947 | − SecureProxyConnectionError | |
| 26965 | + SecureProxyConnectionError, | |
| 26966 | + MessageSizeExceededError | |
| 26948 | 26967 | } |
| 26949 | 26968 | |
| 26950 | 26969 |
@@ -27021,6 +27040,10 @@ class Request {
| 27021 | 27040 | throw new InvalidArgumentError('upgrade must be a string') |
| 27022 | 27041 | } |
| 27023 | 27042 | |
| 27043 | + if (upgrade && !isValidHeaderValue(upgrade)) { | |
| 27044 | + throw new InvalidArgumentError('invalid upgrade header') | |
| 27045 | + } | |
| 27046 | + | |
| 27024 | 27047 | if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { |
| 27025 | 27048 | throw new InvalidArgumentError('invalid headersTimeout') |
| 27026 | 27049 | } |
@@ -27315,13 +27338,19 @@ function processHeader (request, key, val) {
| 27315 | 27338 | val = `${val}` |
| 27316 | 27339 | } |
| 27317 | 27340 | |
| 27318 | − if (request.host === null && headerName === 'host') { | |
| 27341 | + if (headerName === 'host') { | |
| 27342 | + if (request.host !== null) { | |
| 27343 | + throw new InvalidArgumentError('duplicate host header') | |
| 27344 | + } | |
| 27319 | 27345 | if (typeof val !== 'string') { |
| 27320 | 27346 | throw new InvalidArgumentError('invalid host header') |
| 27321 | 27347 | } |
| 27322 | 27348 | // Consumed by Client |
| 27323 | 27349 | request.host = val |
| 27324 | − } else if (request.contentLength === null && headerName === 'content-length') { | |
| 27350 | + } else if (headerName === 'content-length') { | |
| 27351 | + if (request.contentLength !== null) { | |
| 27352 | + throw new InvalidArgumentError('duplicate content-length header') | |
| 27353 | + } | |
| 27325 | 27354 | request.contentLength = parseInt(val, 10) |
| 27326 | 27355 | if (!Number.isFinite(request.contentLength)) { |
| 27327 | 27356 | throw new InvalidArgumentError('invalid content-length header') |
@@ -50038,20 +50067,38 @@ module.exports = {
| 50038 | 50067 | |
| 50039 | 50068 | const { createInflateRaw, Z_DEFAULT_WINDOWBITS } = __nccwpck_require__(8522) |
| 50040 | 50069 | const { isValidClientWindowBits } = __nccwpck_require__(8625) |
| 50070 | +const { MessageSizeExceededError } = __nccwpck_require__(8707) | |
| 50041 | 50071 | |
| 50042 | 50072 | const tail = Buffer.from([0x00, 0x00, 0xff, 0xff]) |
| 50043 | 50073 | const kBuffer = Symbol('kBuffer') |
| 50044 | 50074 | const kLength = Symbol('kLength') |
| 50045 | 50075 | |
| 50076 | +// Default maximum decompressed message size: 4 MB | |
| 50077 | +const kDefaultMaxDecompressedSize = 4 * 1024 * 1024 | |
| 50078 | + | |
| 50046 | 50079 | class PerMessageDeflate { |
| 50047 | 50080 | /** @type {import('node:zlib').InflateRaw} */ |
| 50048 | 50081 | #inflate |
| 50049 | 50082 | |
| 50050 | 50083 | #options = {} |
| 50051 | 50084 | |
| 50052 | − constructor (extensions) { | |
| 50085 | + /** @type {number} */ | |
| 50086 | + #maxDecompressedSize | |
| 50087 | + | |
| 50088 | + /** @type {boolean} */ | |
| 50089 | + #aborted = false | |
| 50090 | + | |
| 50091 | + /** @type {Function|null} */ | |
| 50092 | + #currentCallback = null | |
| 50093 | + | |
| 50094 | + /** | |
| 50095 | + * @param {Map<string, string>} extensions | |
| 50096 | + * @param {{ maxDecompressedMessageSize?: number }} [options] | |
| 50097 | + */ | |
| 50098 | + constructor (extensions, options = {}) { | |
| 50053 | 50099 | this.#options.serverNoContextTakeover = extensions.has('server_no_context_takeover') |
| 50054 | 50100 | this.#options.serverMaxWindowBits = extensions.get('server_max_window_bits') |
| 50101 | + this.#maxDecompressedSize = options.maxDecompressedMessageSize ?? kDefaultMaxDecompressedSize | |
| 50055 | 50102 | } |
| 50056 | 50103 | |
| 50057 | 50104 | decompress (chunk, fin, callback) { |
@@ -50060,6 +50107,11 @@ class PerMessageDeflate {
| 50060 | 50107 | // payload of the message. |
| 50061 | 50108 | // 2. Decompress the resulting data using DEFLATE. |
| 50062 | 50109 | |
| 50110 | + if (this.#aborted) { | |
| 50111 | + callback(new MessageSizeExceededError()) | |
| 50112 | + return | |
| 50113 | + } | |
| 50114 | + | |
| 50063 | 50115 | if (!this.#inflate) { |
| 50064 | 50116 | let windowBits = Z_DEFAULT_WINDOWBITS |
| 50065 | 50117 |
@@ -50072,13 +50124,37 @@ class PerMessageDeflate {
| 50072 | 50124 | windowBits = Number.parseInt(this.#options.serverMaxWindowBits) |
| 50073 | 50125 | } |
| 50074 | 50126 | |
| 50075 | − this.#inflate = createInflateRaw({ windowBits }) | |
| 50127 | + try { | |
| 50128 | + this.#inflate = createInflateRaw({ windowBits }) | |
| 50129 | + } catch (err) { | |
| 50130 | + callback(err) | |
| 50131 | + return | |
| 50132 | + } | |
| 50076 | 50133 | this.#inflate[kBuffer] = [] |
| 50077 | 50134 | this.#inflate[kLength] = 0 |
| 50078 | 50135 | |
| 50079 | 50136 | this.#inflate.on('data', (data) => { |
| 50080 | − this.#inflate[kBuffer].push(data) | |
| 50137 | + if (this.#aborted) { | |
| 50138 | + return | |
| 50139 | + } | |
| 50140 | + | |
| 50081 | 50141 | this.#inflate[kLength] += data.length |
| 50142 | + | |
| 50143 | + if (this.#inflate[kLength] > this.#maxDecompressedSize) { | |
| 50144 | + this.#aborted = true | |
| 50145 | + this.#inflate.removeAllListeners() | |
| 50146 | + this.#inflate.destroy() | |
| 50147 | + this.#inflate = null | |
| 50148 | + | |
| 50149 | + if (this.#currentCallback) { | |
| 50150 | + const cb = this.#currentCallback | |
| 50151 | + this.#currentCallback = null | |
| 50152 | + cb(new MessageSizeExceededError()) | |
| 50153 | + } | |
| 50154 | + return | |
| 50155 | + } | |
| 50156 | + | |
| 50157 | + this.#inflate[kBuffer].push(data) | |
| 50082 | 50158 | }) |
| 50083 | 50159 | |
| 50084 | 50160 | this.#inflate.on('error', (err) => { |
@@ -50087,16 +50163,22 @@ class PerMessageDeflate {
| 50087 | 50163 | }) |
| 50088 | 50164 | } |
| 50089 | 50165 | |
| 50166 | + this.#currentCallback = callback | |
| 50090 | 50167 | this.#inflate.write(chunk) |
| 50091 | 50168 | if (fin) { |
| 50092 | 50169 | this.#inflate.write(tail) |
| 50093 | 50170 | } |
| 50094 | 50171 | |
| 50095 | 50172 | this.#inflate.flush(() => { |
| 50173 | + if (this.#aborted || !this.#inflate) { | |
| 50174 | + return | |
| 50175 | + } | |
| 50176 | + | |
| 50096 | 50177 | const full = Buffer.concat(this.#inflate[kBuffer], this.#inflate[kLength]) |
| 50097 | 50178 | |
| 50098 | 50179 | this.#inflate[kBuffer].length = 0 |
| 50099 | 50180 | this.#inflate[kLength] = 0 |
| 50181 | + this.#currentCallback = null | |
| 50100 | 50182 | |
| 50101 | 50183 | callback(null, full) |
| 50102 | 50184 | }) |
@@ -50150,14 +50232,23 @@ class ByteParser extends Writable {
| 50150 | 50232 | /** @type {Map<string, PerMessageDeflate>} */ |
| 50151 | 50233 | #extensions |
| 50152 | 50234 | |
| 50153 | − constructor (ws, extensions) { | |
| 50235 | + /** @type {{ maxDecompressedMessageSize?: number }} */ | |
| 50236 | + #options | |
| 50237 | + | |
| 50238 | + /** | |
| 50239 | + * @param {import('./websocket').WebSocket} ws | |
| 50240 | + * @param {Map<string, string>|null} extensions | |
| 50241 | + * @param {{ maxDecompressedMessageSize?: number }} [options] | |
| 50242 | + */ | |
| 50243 | + constructor (ws, extensions, options = {}) { | |
| 50154 | 50244 | super() |
| 50155 | 50245 | |
| 50156 | 50246 | this.ws = ws |
| 50157 | 50247 | this.#extensions = extensions == null ? new Map() : extensions |
| 50248 | + this.#options = options | |
| 50158 | 50249 | |
| 50159 | 50250 | if (this.#extensions.has('permessage-deflate')) { |
| 50160 | − this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions)) | |
| 50251 | + this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions, options)) | |
| 50161 | 50252 | } |
| 50162 | 50253 | } |
| 50163 | 50254 |
@@ -50292,6 +50383,7 @@ class ByteParser extends Writable {
| 50292 | 50383 | |
| 50293 | 50384 | const buffer = this.consume(8) |
| 50294 | 50385 | const upper = buffer.readUInt32BE(0) |
| 50386 | + const lower = buffer.readUInt32BE(4) | |
| 50295 | 50387 | |
| 50296 | 50388 | // 2^31 is the maximum bytes an arraybuffer can contain |
| 50297 | 50389 | // on 32-bit systems. Although, on 64-bit systems, this is |
@@ -50299,14 +50391,12 @@ class ByteParser extends Writable {
| 50299 | 50391 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length |
| 50300 | 50392 | // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275 |
| 50301 | 50393 | // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e |
| 50302 | − if (upper > 2 ** 31 - 1) { | |
| 50394 | + if (upper !== 0 || lower > 2 ** 31 - 1) { | |
| 50303 | 50395 | failWebsocketConnection(this.ws, 'Received payload length > 2^31 bytes.') |
| 50304 | 50396 | return |
| 50305 | 50397 | } |
| 50306 | 50398 | |
| 50307 | − const lower = buffer.readUInt32BE(4) | |
| 50308 | − | |
| 50309 | − this.#info.payloadLength = (upper << 8) + lower | |
| 50399 | + this.#info.payloadLength = lower | |
| 50310 | 50400 | this.#state = parserStates.READ_DATA |
| 50311 | 50401 | } else if (this.#state === parserStates.READ_DATA) { |
| 50312 | 50402 | if (this.#byteOffset < this.#info.payloadLength) { |
@@ -50336,7 +50426,7 @@ class ByteParser extends Writable {
| 50336 | 50426 | } else { |
| 50337 | 50427 | this.#extensions.get('permessage-deflate').decompress(body, this.#info.fin, (error, data) => { |
| 50338 | 50428 | if (error) { |
| 50339 | − closeWebSocketConnection(this.ws, 1007, error.message, error.message.length) | |
| 50429 | + failWebsocketConnection(this.ws, error.message) | |
| 50340 | 50430 | return |
| 50341 | 50431 | } |
| 50342 | 50432 |
@@ -50940,6 +51030,12 @@ function parseExtensions (extensions) {
| 50940 | 51030 | * @param {string} value |
| 50941 | 51031 | */ |
| 50942 | 51032 | function isValidClientWindowBits (value) { |
| 51033 | + // Must have at least one character | |
| 51034 | + if (value.length === 0) { | |
| 51035 | + return false | |
| 51036 | + } | |
| 51037 | + | |
| 51038 | + // Check all characters are ASCII digits | |
| 50943 | 51039 | for (let i = 0; i < value.length; i++) { |
| 50944 | 51040 | const byte = value.charCodeAt(i) |
| 50945 | 51041 |
@@ -50948,7 +51044,9 @@ function isValidClientWindowBits (value) {
| 50948 | 51044 | } |
| 50949 | 51045 | } |
| 50950 | 51046 | |
| 50951 | − return true | |
| 51047 | + // Check numeric range: zlib requires windowBits in range 8-15 | |
| 51048 | + const num = Number.parseInt(value, 10) | |
| 51049 | + return num >= 8 && num <= 15 | |
| 50952 | 51050 | } |
| 50953 | 51051 | |
| 50954 | 51052 | // https://nodejs.org/api/intl.html#detecting-internationalization-support |
@@ -51039,6 +51137,9 @@ class WebSocket extends EventTarget {
| 51039 | 51137 | /** @type {SendQueue} */ |
| 51040 | 51138 | #sendQueue |
| 51041 | 51139 | |
| 51140 | + /** @type {{ maxDecompressedMessageSize?: number }} */ | |
| 51141 | + #options | |
| 51142 | + | |
| 51042 | 51143 | /** |
| 51043 | 51144 | * @param {string} url |
| 51044 | 51145 | * @param {string|string[]} protocols |
@@ -51112,6 +51213,11 @@ class WebSocket extends EventTarget {
| 51112 | 51213 | // 10. Set this's url to urlRecord. |
| 51113 | 51214 | this[kWebSocketURL] = new URL(urlRecord.href) |
| 51114 | 51215 | |
| 51216 | + // Store options for later use (e.g., maxDecompressedMessageSize) | |
| 51217 | + this.#options = { | |
| 51218 | + maxDecompressedMessageSize: options.maxDecompressedMessageSize | |
| 51219 | + } | |
| 51220 | + | |
| 51115 | 51221 | // 11. Let client be this's relevant settings object. |
| 51116 | 51222 | const client = environmentSettingsObject.settingsObject |
| 51117 | 51223 |
@@ -51426,11 +51532,11 @@ class WebSocket extends EventTarget {
| 51426 | 51532 | * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol |
| 51427 | 51533 | */ |
| 51428 | 51534 | #onConnectionEstablished (response, parsedExtensions) { |
| 51429 | − // processResponse is called when the "response’s header list has been received and initialized." | |
| 51535 | + // processResponse is called when the "response's header list has been received and initialized." | |
| 51430 | 51536 | // once this happens, the connection is open |
| 51431 | 51537 | this[kResponse] = response |
| 51432 | 51538 | |
| 51433 | − const parser = new ByteParser(this, parsedExtensions) | |
| 51539 | + const parser = new ByteParser(this, parsedExtensions, this.#options) | |
| 51434 | 51540 | parser.on('drain', onParserDrain) |
| 51435 | 51541 | parser.on('error', onParserError.bind(this)) |
| 51436 | 51542 |
@@ -51533,6 +51639,19 @@ webidl.converters.WebSocketInit = webidl.dictionaryConverter([
| 51533 | 51639 | { |
| 51534 | 51640 | key: 'headers', |
| 51535 | 51641 | converter: webidl.nullableConverter(webidl.converters.HeadersInit) |
| 51642 | + }, | |
| 51643 | + { | |
| 51644 | + key: 'maxDecompressedMessageSize', | |
| 51645 | + converter: webidl.nullableConverter((V) => { | |
| 51646 | + V = webidl.converters['unsigned long long'](V) | |
| 51647 | + if (V <= 0) { | |
| 51648 | + throw webidl.errors.exception({ | |
| 51649 | + header: 'WebSocket constructor', | |
| 51650 | + message: 'maxDecompressedMessageSize must be greater than 0' | |
| 51651 | + }) | |
| 51652 | + } | |
| 51653 | + return V | |
| 51654 | + }) | |
| 51536 | 51655 | } |
| 51537 | 51656 | ]) |
| 51538 | 51657 |
modified
package-lock.json
+3
−3
@@ -3626,9 +3626,9 @@
| 3626 | 3626 | } |
| 3627 | 3627 | }, |
| 3628 | 3628 | "node_modules/undici": { |
| 3629 | − "version": "6.23.0", | |
| 3630 | − "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", | |
| 3631 | − "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==", | |
| 3629 | + "version": "6.24.0", | |
| 3630 | + "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.0.tgz", | |
| 3631 | + "integrity": "sha512-lVLNosgqo5EkGqh5XUDhGfsMSoO8K0BAN0TyJLvwNRSl4xWGZlCVYsAIpa/OpA3TvmnM01GWcoKmc3ZWo5wKKA==", | |
| 3632 | 3632 | "license": "MIT", |
| 3633 | 3633 | "engines": { |
| 3634 | 3634 | "node": ">=18.17" |
Parents: 1380ebe