From 9686bf6653e873480a6c319191c82e8df42d012c Mon Sep 17 00:00:00 2001 From: ctcpip Date: Mon, 23 Jun 2025 12:41:28 -0500 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=A5=85=20improve=20error=20handling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/make-middleware.js | 15 ++++++++----- test/express-integration.js | 42 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/lib/make-middleware.js b/lib/make-middleware.js index dc3483b4..f79168b7 100644 --- a/lib/make-middleware.js +++ b/lib/make-middleware.js @@ -101,6 +101,15 @@ function makeMiddleware (setup) { // handle files busboy.on('file', function (fieldname, fileStream, { filename, encoding, mimeType }) { + var pendingWritesIncremented = false + + fileStream.on('error', function (err) { + if (pendingWritesIncremented) { + pendingWrites.decrement() + } + abortWithError(err) + }) + if (fieldname == null) return abortWithCode('MISSING_FIELD_NAME') // filename is not required (https://tools.ietf.org/html/rfc1867) but if @@ -134,6 +143,7 @@ function makeMiddleware (setup) { } var aborting = false + pendingWritesIncremented = true pendingWrites.increment() Object.defineProperty(file, 'stream', { @@ -142,11 +152,6 @@ function makeMiddleware (setup) { value: fileStream }) - fileStream.on('error', function (err) { - pendingWrites.decrement() - abortWithError(err) - }) - fileStream.on('limit', function () { aborting = true abortWithCode('LIMIT_FILE_SIZE', fieldname) diff --git a/test/express-integration.js b/test/express-integration.js index ff1757b4..6860f4f6 100644 --- a/test/express-integration.js +++ b/test/express-integration.js @@ -196,4 +196,46 @@ describe('Express Integration', function () { req.write(body) req.end() }) + + it('should not crash on malformed multipart body with bad boundary', function (done) { + var upload = multer() + + app.post('/upload3', upload.single('image'), function (req, res) { + res.status(500).end('Request should not be processed') + }) + + app.use(function (err, req, res, next) { + assert.strictEqual(err.message, 'Unexpected end of form') + res.status(200).end('Correct error') + }) + + var boundary = '----FormBoundary' + var body = [ + '------FormBoundary', + 'Content-Disposition: form-data; name="image"; filename=""', + 'Content-Type: application/octet-stream', + '', + '', // empty content + '------FormBoundar' // intentionally malformed final boundary (missing 'y') + ].join('\r\n') + + var options = { + hostname: 'localhost', + port, + path: '/upload3', + method: 'POST', + headers: { + 'Content-Type': 'multipart/form-data; boundary=' + boundary, + 'Content-Length': Buffer.byteLength(body) + } + } + + var req = http.request(options, (res) => { + assert.strictEqual(res.statusCode, 200) + done() + }) + + req.write(body) + req.end() + }) }) From 475f3d4938f6d8d07971eeda76a3109911c347df Mon Sep 17 00:00:00 2001 From: ctcpip Date: Mon, 23 Jun 2025 13:04:07 -0500 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=94=96=202.0.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8dd9f91..bfe1b0f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 2.0.2 + +- Fix [CVE-2025-7338](https://www.cve.org/CVERecord?id=CVE-2025-7338) ([GHSA-fjgf-rc76-4x9p](https://github.com/expressjs/multer/security/advisories/GHSA-fjgf-rc76-4x9p)) + + ## 2.0.1 - Fix [CVE-2025-48997](https://www.cve.org/CVERecord?id=CVE-2025-48997) ([GHSA-g5hg-p3ph-g8qg](https://github.com/expressjs/multer/security/advisories/GHSA-g5hg-p3ph-g8qg)) diff --git a/package.json b/package.json index a5d3ac73..de464f55 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "multer", "description": "Middleware for handling `multipart/form-data`.", - "version": "2.0.1", + "version": "2.0.2", "contributors": [ "Hage Yaapa (http://www.hacksparrow.com)", "Jaret Pfluger ", From f3d67942abd11454e63c71103743b840141297a2 Mon Sep 17 00:00:00 2001 From: Andrew Rumble Date: Fri, 18 Jul 2025 15:17:01 +0100 Subject: [PATCH 3/3] Fix lint in filename tests --- test/no-filename.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/no-filename.js b/test/no-filename.js index 5ed55ced..9de101f8 100644 --- a/test/no-filename.js +++ b/test/no-filename.js @@ -27,9 +27,9 @@ describe('File with no filename', function () { parser(req, null, function (err) { onFinished(req, function () { assert.ifError(err) - assert.equal(req.files.length, 1) - assert.equal(req.files[0].fieldname, 'fileField') - assert.equal(req.files[0].buffer.toString(), 'foo') + assert.strict.equal(req.files.length, 1) + assert.strict.equal(req.files[0].fieldname, 'fileField') + assert.strict.equal(req.files[0].buffer.toString(), 'foo') done() }) })