From d235a2dcd126c24a519ccb1a19b3d3007ccc1ded Mon Sep 17 00:00:00 2001 From: tsctx <91457664+tsctx@users.noreply.github.com> Date: Mon, 25 Dec 2023 22:25:30 +0900 Subject: [PATCH 1/2] fix: check the content-type of invalid formData --- lib/fetch/body.js | 10 ++++++---- test/fetch/response.js | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/lib/fetch/body.js b/lib/fetch/body.js index 6202887289a..8f417fe77b1 100644 --- a/lib/fetch/body.js +++ b/lib/fetch/body.js @@ -14,7 +14,7 @@ const { FormData } = require('./formdata') const { kState } = require('./symbols') const { webidl } = require('./webidl') const { Blob, File: NativeFile } = require('buffer') -const { kBodyUsed } = require('../core/symbols') +const { kBodyUsed, kHeadersList } = require('../core/symbols') const assert = require('assert') const { isErrored } = require('../core/util') const { isUint8Array, isArrayBuffer } = require('util/types') @@ -369,10 +369,12 @@ function bodyMixinMethods (instance) { throwIfAborted(this[kState]) - const contentType = this.headers.get('Content-Type') + const contentType = this.headers[kHeadersList].get('content-type', true) + + const essence = contentType !== null && parseMIMEType(contentType) // If mimeType’s essence is "multipart/form-data", then: - if (/multipart\/form-data/.test(contentType)) { + if (essence === 'multipart/form-data') { const headers = {} for (const [key, value] of this.headers) headers[key] = value @@ -430,7 +432,7 @@ function bodyMixinMethods (instance) { await busboyResolve return responseFormData - } else if (/application\/x-www-form-urlencoded/.test(contentType)) { + } else if (essence === 'application/x-www-form-urlencoded') { // Otherwise, if mimeType’s essence is "application/x-www-form-urlencoded", then: // 1. Let entries be the result of parsing bytes. diff --git a/test/fetch/response.js b/test/fetch/response.js index 066adb1e7b3..b9aacd7a623 100644 --- a/test/fetch/response.js +++ b/test/fetch/response.js @@ -2,7 +2,8 @@ const { test } = require('tap') const { - Response + Response, + FormData } = require('../../') const { Blob: ThirdPartyBlob, @@ -254,3 +255,35 @@ test('Issue#2465', async (t) => { const response = new Response(new SharedArrayBuffer(0)) t.equal(await response.text(), '[object SharedArrayBuffer]') }) + +test('Check the Content-Type of invalid formData', (t) => { + t.plan(4) + + t.test('_application/x-www-form-urlencoded', async (t) => { + t.plan(1) + const response = new Response('x=y', { headers: { 'content-type': '_application/x-www-form-urlencoded' } }) + await t.rejects(response.formData(), TypeError) + }) + + t.test('_multipart/form-data', async (t) => { + t.plan(1) + const formData = new FormData() + formData.append('x', 'y') + const response = new Response(formData, { headers: { 'content-type': '_multipart/form-data' } }) + await t.rejects(response.formData(), TypeError) + }) + + t.test('application/x-www-form-urlencoded_', async (t) => { + t.plan(1) + const response = new Response('x=y', { headers: { 'content-type': 'application/x-www-form-urlencoded_' } }) + await t.rejects(response.formData(), TypeError) + }) + + t.test('multipart/form-data_', async (t) => { + t.plan(1) + const formData = new FormData() + formData.append('x', 'y') + const response = new Response(formData, { headers: { 'content-type': 'multipart/form-data_' } }) + await t.rejects(response.formData(), TypeError) + }) +}) From 1b4cf453edf325be0fbe711ceb1a96e46ef3f381 Mon Sep 17 00:00:00 2001 From: tsctx <91457664+tsctx@users.noreply.github.com> Date: Mon, 25 Dec 2023 22:44:11 +0900 Subject: [PATCH 2/2] fixup --- lib/fetch/body.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fetch/body.js b/lib/fetch/body.js index 8f417fe77b1..16914c14c8f 100644 --- a/lib/fetch/body.js +++ b/lib/fetch/body.js @@ -371,10 +371,10 @@ function bodyMixinMethods (instance) { const contentType = this.headers[kHeadersList].get('content-type', true) - const essence = contentType !== null && parseMIMEType(contentType) + const mimeType = contentType !== null ? parseMIMEType(contentType) : 'failure' // If mimeType’s essence is "multipart/form-data", then: - if (essence === 'multipart/form-data') { + if (mimeType !== 'failure' && mimeType.essence === 'multipart/form-data') { const headers = {} for (const [key, value] of this.headers) headers[key] = value @@ -432,7 +432,7 @@ function bodyMixinMethods (instance) { await busboyResolve return responseFormData - } else if (essence === 'application/x-www-form-urlencoded') { + } else if (mimeType !== 'failure' && mimeType.essence === 'application/x-www-form-urlencoded') { // Otherwise, if mimeType’s essence is "application/x-www-form-urlencoded", then: // 1. Let entries be the result of parsing bytes.