CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-3304
8.70.04%

Denial of Service via Incomplete File Cleanup in Multer Middleware

Amit Schendel
Amit Schendel
Senior Security Researcher

Mar 1, 2026·6 min read·10 visits

PoC Available

Executive Summary (TL;DR)

Multer < 2.1.0 fails to delete temporary files if a request errors out while an asynchronous file filter is running. Attackers can flood the server with requests that trigger this condition, filling the disk and crashing the application.

A critical resource exhaustion vulnerability exists in the Multer Node.js middleware versions prior to 2.1.0. The issue arises from a race condition between asynchronous file filtering and stream error handling. When a request triggers an error during the processing of a multipart stream, files that were pending validation in an asynchronous `fileFilter` are not properly cleaned up from the disk. This allows remote attackers to exhaust the server's storage capacity by repeatedly sending crafted requests, leading to a Denial of Service (DoS).

Vulnerability Overview

Multer is a popular middleware for handling multipart/form-data in Node.js applications, primarily used for file uploads. It processes incoming file streams, writes them to a destination (disk or memory), and provides hooks for validation via the fileFilter option. CVE-2026-3304 identifies a logic flaw in how Multer manages resource lifecycles when these validation hooks operate asynchronously.

The core of the vulnerability is a desynchronization between the global request state and individual file processing. When Multer receives a file, it may write it to a temporary location before deciding whether to keep it (based on fileFilter). If the fileFilter is asynchronous—common for lookups like malware scanning or quota checking—the underlying multipart parser (Busboy) continues processing the rest of the request stream.

If a fatal error occurs in the stream (e.g., a malformed subsequent part) while the fileFilter is still pending, the global error handler is triggered. However, in vulnerable versions, the callback for the pending fileFilter does not check this global error state upon completion. Consequently, the temporary file written to disk is effectively "orphaned." It is neither passed to the application nor deleted, remaining on the filesystem indefinitely. Repeated exploitation leads to complete disk exhaustion and service unavailability.

Root Cause Analysis

The vulnerability stems from the implementation of the make-middleware.js module in Multer. Specifically, it involves the interaction between the appender (responsible for writing data) and the fileFilter (responsible for validation).

When a file header is parsed, Multer invokes appender.insertPlaceholder. If the configured storage engine is DiskStorage, this creates a file on disk immediately. Multer then invokes the user-provided fileFilter. The logic flaw resides in the callback wrapper for this filter.

Prior to version 2.1.0, the callback only handled errors explicitly passed to it or the boolean decision to include the file. It failed to inspect the errorOccured flag, which tracks the health of the overall request stream. If the multipart parser encountered a protocol violation (such as a part missing the Content-Disposition name) after the file processing started but before the asynchronous filter completed, the errorOccured flag would be set to true.

However, when the asynchronous filter eventually resolved, the code proceeded as if the stream were healthy. Crucially, it bypassed the appender.removePlaceholder(placeholder) call that is necessary to clean up files when an operation is aborted. This specific execution path—async wait combined with stream failure—creates a zombie file on the filesystem.

Code Analysis

The fix was applied in lib/make-middleware.js by introducing a check for the errorOccured state within the fileFilter callback. This ensures that if the request has already failed, the pending file is immediately cleaned up.

Vulnerable Code (Simplified):

// Inside make-middleware.js
fileFilter(req, file, function (err, includeFile) {
  if (err) {
    appender.removePlaceholder(placeholder)
    return next(err)
  }
 
  if (!includeFile) {
    appender.removePlaceholder(placeholder)
    return fileStream.resume()
  }
 
  // ... proceed to save file ...
  // CRITICAL MISSING CHECK: Does not verify if the request crashed elsewhere
})

Patched Code:

The patch introduces a guard clause at the very beginning of the callback. This logic acknowledges that if the request stream has already error-ed out (due to malformed data later in the stream), the current file is irrelevant and must be removed.

// Inside make-middleware.js (Fixed)
fileFilter(req, file, function (err, includeFile) {
  // NEW: Check global error state before proceeding
  if (errorOccured) {
    appender.removePlaceholder(placeholder)
    return fileStream.resume()
  }
 
  if (err) {
    appender.removePlaceholder(placeholder)
    return next(err)
  }
 
  if (!includeFile) {
    appender.removePlaceholder(placeholder)
    return fileStream.resume()
  }
 
  // ... proceed to save file ...
})

This simple addition ensures that the removePlaceholder method is called even when the error originated outside the scope of the current file's filter function.

Exploitation Mechanics

To exploit CVE-2026-3304, an attacker does not need authentication or special privileges. They simply need to send a crafted multipart/form-data request to an endpoint utilizing Multer with an asynchronous fileFilter. The attack relies on timing and stream ordering.

Attack Steps:

  1. Initiate Upload: The attacker sends a multipart request. The first part is a valid file upload (e.g., file1.png).
  2. Trigger Async Wait: The server receives file1.png, writes it to the temporary directory, and calls the asynchronous fileFilter (e.g., checking if the file signature is allowed). This pauses processing for this specific file while the Node.js event loop continues.
  3. Inject Malformed Part: The attacker immediately sends the next part of the body. This part is intentionally malformed—specifically, it might contain a Content-Disposition header but lack the required name parameter.
  4. Trigger Error: Multer's parser (Busboy) parses the second part, detects the protocol violation, and triggers an 'error' event on the request. The errorOccured flag is set to true.
  5. Leak Resource: The asynchronous fileFilter for file1.png completes. Because the vulnerable code doesn't check errorOccured, it assumes success or simply ignores the cleanup path. The request terminates, but file1.png remains in the temporary folder.

By scripting this process to occur in a loop, an attacker can rapidly fill the server's disk space with orphaned temporary files.

Impact Assessment

The primary impact of this vulnerability is Denial of Service (DoS) via disk resource exhaustion. In a cloud environment or containerized deployment with ephemeral storage, the impact may be temporary until the container restarts. However, in persistent hosting environments, this can lead to prolonged downtime.

Consequences:

  • Service Crash: When the disk is full, the application will likely crash when attempting to write logs, session data, or new uploads.
  • System Instability: If the dest directory is on the root partition, the entire operating system may become unstable, affecting other services running on the same host.
  • Cost Implications: For cloud environments with auto-scaling storage, this attack could lead to significant financial costs due to rapid storage expansion before the attack is mitigated.

CVSS 4.0 Assessment:

  • Score: 8.7 (High)
  • Vector: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
  • Analysis: The attack vector is network-based (AV:N) and requires no privileges (PR:N). The impact is solely on Availability (VA:H), with no Confidentiality or Integrity loss. The attack complexity is low (AC:L) as it requires only standard HTTP manipulation tools.

Official Patches

expressjsMulter v2.1.0 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
8.7/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
EPSS Probability
0.04%
Top 87% most exploited

Affected Systems

Node.js applications using Multer < 2.1.0Express.js applications using Multer < 2.1.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
multer
expressjs
< 2.1.02.1.0
AttributeDetail
CWE IDCWE-459
Vulnerability TypeResource Exhaustion (DoS)
CVSS 4.08.7 (High)
Attack VectorNetwork
Affected Componentmake-middleware.js
PrerequisitesAsynchronous fileFilter configuration

MITRE ATT&CK Mapping

T1499.003Endpoint Denial of Service: Resource Exhaustion
Impact
CWE-459
Incomplete Cleanup

Vulnerability Timeline

Patch committed to GitHub repository
2026-02-26
GHSA Advisory Published
2026-02-27
CVE-2026-3304 Published
2026-02-27

References & Sources

  • [1]GHSA-xf7r-hgr6-v32p: Denial of Service in Multer
  • [2]NVD - CVE-2026-3304