VYPR
Critical severity9.1NVD Advisory· Published May 18, 2026· Updated May 18, 2026

CVE-2026-45230

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

Patches

1
1e0943d9f35a

Merge 22363e676511284e90542b92bfc6329a39392e44 into 2bacca1e2c4ff8e60d562c8dc300a8dbe91083c3

https://github.com/DumbWareio/DumbAssetsYoanMay 16, 2026via nvd-ref
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

2

News mentions

0

No linked articles in our index yet.