From 4d8931ca8a92e53c5dcf02cf46d1016a10e60ec0 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Mar 2026 16:08:47 +0200 Subject: [PATCH] fix: formidable dependency vulnerable to arbitrary (#7533) * fix: dependabot uses the correct labels * fix: issue #7463 * fix: update to the latest version of formidable --- package-lock.json | 14 ++++++++------ package.json | 2 +- tests/setup/server.js | 4 ++-- tests/unit/adapters/http.test.js | 28 ++++++++++++++-------------- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index 04771991..f6b85a86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "eslint": "^10.0.3", "express": "^5.2.1", "formdata-node": "^5.0.1", - "formidable": "^2.1.5", + "formidable": "^3.2.4", "fs-extra": "^10.1.0", "get-stream": "^9.0.1", "globals": "^17.4.0", @@ -7094,16 +7094,18 @@ } }, "node_modules/formidable": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz", - "integrity": "sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", "dev": true, "license": "MIT", "dependencies": { "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", - "once": "^1.4.0", - "qs": "^6.11.0" + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" }, "funding": { "url": "https://ko-fi.com/tunnckoCore/commissions" diff --git a/package.json b/package.json index 92a87c6a..b6125fea 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "eslint": "^10.0.3", "express": "^5.2.1", "formdata-node": "^5.0.1", - "formidable": "^2.1.5", + "formidable": "^3.2.4", "fs-extra": "^10.1.0", "get-stream": "^9.0.1", "globals": "^17.4.0", diff --git a/tests/setup/server.js b/tests/setup/server.js index 317fbcf9..7d345562 100644 --- a/tests/setup/server.js +++ b/tests/setup/server.js @@ -3,7 +3,7 @@ import http2 from 'http2'; import stream from 'stream'; import getStream, { getStreamAsBuffer } from 'get-stream'; import { Throttle } from 'stream-throttle'; -import formidable from 'formidable'; +import { IncomingForm } from 'formidable'; import selfsigned from 'selfsigned'; export const SERVER_HANDLER_STREAM_ECHO = (req, res) => req.pipe(res); @@ -124,7 +124,7 @@ export const stopAllTrackedHTTPServers = async (timeout = 10000) => { export const handleFormData = (req) => { return new Promise((resolve, reject) => { - const form = new formidable.IncomingForm(); + const form = new IncomingForm(); form.parse(req, (err, fields, files) => { if (err) { diff --git a/tests/unit/adapters/http.test.js b/tests/unit/adapters/http.test.js index c7ff5dcb..c94d98a1 100644 --- a/tests/unit/adapters/http.test.js +++ b/tests/unit/adapters/http.test.js @@ -22,7 +22,7 @@ import os from 'os'; import path from 'path'; import devNull from 'dev-null'; import FormDataLegacy from 'form-data'; -import formidable from 'formidable'; +import { IncomingForm } from 'formidable'; import { FormData as FormDataPolyfill, Blob as BlobPolyfill } from 'formdata-node'; import express from 'express'; import multer from 'multer'; @@ -2285,7 +2285,7 @@ describe('supports http with nodejs', () => { const server = await startHTTPServer( (req, res) => { - const receivedForm = new formidable.IncomingForm(); + const receivedForm = new IncomingForm(); assert.ok(req.rawHeaders.some((header) => header.toLowerCase() === 'content-length')); @@ -2314,15 +2314,15 @@ describe('supports http with nodejs', () => { }, }); - assert.deepStrictEqual(response.data.fields, { foo: 'bar' }); + assert.deepStrictEqual(response.data.fields, { foo: ['bar'] }); - assert.strictEqual(response.data.files.file1.mimetype, 'image/jpeg'); - assert.strictEqual(response.data.files.file1.originalFilename, 'temp/bar.jpg'); - assert.strictEqual(response.data.files.file1.size, 3); + assert.strictEqual(response.data.files.file1[0].mimetype, 'image/jpeg'); + assert.strictEqual(response.data.files.file1[0].originalFilename, 'temp/bar.jpg'); + assert.strictEqual(response.data.files.file1[0].size, 3); - assert.strictEqual(response.data.files.fileStream.mimetype, 'image/png'); - assert.strictEqual(response.data.files.fileStream.originalFilename, 'axios.png'); - assert.strictEqual(response.data.files.fileStream.size, stat.size); + assert.strictEqual(response.data.files.fileStream[0].mimetype, 'image/png'); + assert.strictEqual(response.data.files.fileStream[0].originalFilename, 'axios.png'); + assert.strictEqual(response.data.files.fileStream[0].size, stat.size); } finally { await stopHTTPServer(server); } @@ -2358,10 +2358,10 @@ describe('supports http with nodejs', () => { maxRedirects: 0, }); - assert.deepStrictEqual(data.fields, { foo1: 'bar1', foo2: 'bar2' }); - assert.deepStrictEqual(typeof data.files.file1, 'object'); + assert.deepStrictEqual(data.fields, { foo1: ['bar1'], foo2: ['bar2'] }); + assert.deepStrictEqual(typeof data.files.file1[0], 'object'); - const { size, mimetype, originalFilename } = data.files.file1; + const { size, mimetype, originalFilename } = data.files.file1[0]; assert.deepStrictEqual( { size, mimetype, originalFilename }, @@ -3270,8 +3270,8 @@ describe('supports http with nodejs', () => { assert.deepStrictEqual(data, { fields: { - x: 'foo', - y: 'bar', + x: ['foo'], + y: ['bar'], }, files: {}, });