CVE-2026-45230
Description
DumbAssets through 1.0.11 contains a path traversal vulnerability in the POST /api/delete-file endpoint and filesToDelete array parameters that allows unauthenticated attackers to delete arbitrary files by supplying ../ sequences that bypass directory boundary validation. Attackers can exploit the optional and disabled-by-default authentication control to traverse outside the intended application directory and delete critical files such as server.js or package.json, causing complete denial of service.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Unauthenticated path traversal in DumbAssets <=1.0.11 /api/delete-file allows arbitrary file deletion, leading to denial of service.
Vulnerability
DumbAssets through version 1.0.11 contains a path traversal vulnerability in the POST /api/delete-file endpoint. The filesToDelete array parameter accepts user-supplied paths that are resolved with path.join() without verifying the result stays within the intended data directory. This allows unauthenticated attackers to supply ../ sequences to traverse outside the application directory and delete arbitrary files. The authentication control is optional and disabled by default, making the endpoint accessible without credentials. [1][2]
Exploitation
An attacker can send a crafted POST request to /api/delete-file with a filesToDelete array containing paths such as ../../../server.js or ../../../package.json. The server processes these paths using path.join() and deleteAssetFileAsync(), which does not validate that the resolved path remains under the base directory. No authentication is required because the optional authentication is disabled by default. The attacker can repeatedly delete critical files to disrupt the application. [1][2]
Impact
Successful exploitation allows an unauthenticated attacker to delete arbitrary files that the Node.js process has write access to, including core application files like server.js or package.json. This results in a complete denial of service (DoS) as the application becomes non-functional. The vulnerability has high impact on integrity and availability, with no impact on confidentiality. [1]
Mitigation
The vulnerability is fixed in DumbAssets version 1.0.12, released via pull request #136. The fix introduces resolveDataFilePath() that normalizes paths using path.resolve() and rejects any path that escapes the DATA_DIR directory, additionally restricting deletions to legitimate upload subdirectories (Images/, Receipts/, Manuals/). Users should upgrade to version 1.0.12 or later. If immediate upgrade is not possible, enabling authentication and restricting network access to the /api/delete-file endpoint may reduce risk, but the only complete mitigation is applying the patch. [2]
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2(expand)+ 1 more
- (no CPE)
- (no CPE)range: <=1.0.11
Patches
11e0943d9f35aMerge 22363e676511284e90542b92bfc6329a39392e44 into 2bacca1e2c4ff8e60d562c8dc300a8dbe91083c3
1 file changed · +29 −5
server.js+29 −5 modified@@ -494,16 +494,36 @@ function generateId() { return Math.floor(1000000000 + Math.random() * 9000000000).toString(); } +// Subdirectories under DATA_DIR that legitimately hold uploaded asset files. +// Any path resolved outside one of these is rejected to prevent path traversal. +const ALLOWED_ASSET_FILE_SUBDIRS = ['Images', 'Receipts', 'Manuals']; + +function resolveDataFilePath(filePath) { + if (typeof filePath !== 'string') return null; + const cleanPath = filePath.replace(/^\/+/, ''); + if (!cleanPath) return null; + const resolved = path.resolve(DATA_DIR, cleanPath); + const dataDirPrefix = DATA_DIR + path.sep; + if (resolved !== DATA_DIR && !resolved.startsWith(dataDirPrefix)) return null; + const relative = path.relative(DATA_DIR, resolved); + const topDir = relative.split(path.sep)[0]; + if (!ALLOWED_ASSET_FILE_SUBDIRS.includes(topDir)) return null; + return resolved; +} + function deleteAssetFileAsync(filePath) { return new Promise((resolve, reject) => { if (!filePath) { console.log('[DEBUG] Skipping empty filePath'); return resolve(); } - // File paths are stored as '/Images/filename.jpg', so we need to join with DATA_DIR - // and remove the leading slash to avoid double slashes - const cleanPath = filePath.startsWith('/') ? filePath.substring(1) : filePath; - const fullPath = path.join(DATA_DIR, cleanPath); + // File paths are stored as '/Images/filename.jpg' and must resolve + // inside DATA_DIR/{Images,Receipts,Manuals} — reject any traversal. + const fullPath = resolveDataFilePath(filePath); + if (!fullPath) { + console.warn(`[SECURITY] Path traversal blocked in deleteAssetFileAsync: ${filePath}`); + return resolve(); + } console.log(`[DEBUG] Attempting to delete file: ${fullPath}`); fs.unlink(fullPath, (err) => { if (err && err.code !== 'ENOENT') { @@ -1210,7 +1230,11 @@ app.post('/api/upload/manual', uploadManual.array('manual', 10), (req, res) => { app.post('/api/delete-file', (req, res) => { const { path: filePath } = req.body; if (!filePath) return res.status(400).json({ error: 'No file path provided' }); - const absPath = path.join(__dirname, filePath.startsWith('/') ? filePath.substring(1) : filePath); + const absPath = resolveDataFilePath(filePath); + if (!absPath) { + console.warn(`[SECURITY] Path traversal blocked in /api/delete-file: ${filePath}`); + return res.status(400).json({ error: 'Invalid file path' }); + } fs.unlink(absPath, (err) => { if (err) { // If file doesn't exist, treat as success
Vulnerability mechanics
Root cause
"Missing path validation in the POST /api/delete-file endpoint allows an unauthenticated attacker to supply ../ sequences that resolve outside the intended data directory."
Attack vector
An unauthenticated attacker sends a POST request to /api/delete-file with a JSON body containing a filesToDelete array (or a path field) that includes ../ sequences, e.g. {"path":"../../server.js"}. The server joins this user-supplied path with DATA_DIR without validating that the resolved path stays within allowed subdirectories. Because authentication is optional and disabled by default, no credentials are required. The attacker can delete arbitrary files such as server.js or package.json, causing complete denial of service. [CWE-22]
Affected code
The vulnerability exists in server.js within the POST /api/delete-file route handler and the deleteAssetFileAsync() function. Both code paths join user-supplied file paths with DATA_DIR using path.join() without validating that the resolved path stays within allowed subdirectories. The patch modifies these functions to use the new resolveDataFilePath() helper. [patch_id=424433]
What the fix does
The patch introduces a resolveDataFilePath() function that performs three checks: it normalizes the path, verifies the resolved path is under DATA_DIR, and ensures the top-level subdirectory is one of the allowed set (Images, Receipts, Manuals). Both deleteAssetFileAsync() and the /api/delete-file route now call this function and reject any path that fails validation. This closes the traversal by preventing any path that escapes the allowed subdirectories from reaching fs.unlink(). [patch_id=424433]
Preconditions
- configAuthentication is optional and disabled by default
- networkAttacker can reach the POST /api/delete-file endpoint over the network
- inputAttacker supplies a path containing ../ traversal sequences
Generated on May 19, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.