CVE-2024-0549 (JavaScript, published 2024-04-16T00:15Z)
Description: value: mintplex-labs/anything-llm is vulnerable to a relative path traversal attack, allowing unauthorized attackers with a default role account to delete files and folders within the filesystem, including critical database files such as 'anythingllm.db'. The vulnerability stems from insufficient input validation and normalization in the handling of file and folder deletion requests. Successful exploitation results in the compromise of data integrity and availability.
Severity: nan (CVSS v3 base score: )
Weakness: CWE-23 \u2014 Relative Path Traversal
The product uses external input to construct a pathname that should be within a restricted directory, but it does not properly neutralize sequences such as ".." that can resolve to a location that is outside of that directory.
Repository: https://github.com/mintplex-labs/anything-llm
Files changed:
server/endpoints/system.js
server/utils/files/index.js
server/utils/files/purgeDocument.js
Commit message: normalize paths for submit URLs of  `remove-documents (#598)

normalize paths for submit URLs

Vulnerable code:
const { viewLocalFiles } = require("../utils/files");
    const sanitized = path
      .normalize(request.params.filename)
      .replace(/^(\.\.(\/|\\|$))+/, "");
async function collectDocumentData(folderName = null) {
  if (!folderName) throw new Error("No docPath provided in request");
  const folder =
    process.env.NODE_ENV === "development"
      ? path.resolve(__dirname, `../../storage/documents/${folderName}`)
      : path.resolve(process.env.STORAGE_DIR, `documents/${folderName}`);

  const dirExists = fs.existsSync(folder);
  if (!dirExists)
    throw new Error(
      `No documents folder for ${folderName} - did you run collector/main.py for this element?`
    );

  const files = fs.readdirSync(folder);
  const fileData = [];
  files.forEach((file) => {
    if (path.extname(file) === ".json") {
      const filePath = path.join(folder, file);
      const data = fs.readFileSync(filePath, "utf8");
      console.log(`Parsing document: ${file}`);
      fileData.push(JSON.parse(data));
    }
  });
  return fileData;
}

      ? path.resolve(__dirname, `../../storage/documents/${filePath}`)
      : path.resolve(process.env.STORAGE_DIR, `documents/${filePath}`);

      ? path.resolve(__dirname, `../../storage/documents`, filename)
      : path.resolve(process.env.STORAGE_DIR, `documents`, filename);
  collectDocumentData,

const { purgeVectorCache, purgeSourceDocument } = require(".");
  const folderPath = path.resolve(documentsFolder, folderName);
    .map((file) => path.join(folderName, file));

Fixed code:
const { viewLocalFiles, normalizePath } = require("../utils/files");
    const sanitized = normalizePath(request.params.filename);
      ? path.resolve(
          __dirname,
          `../../storage/documents/${normalizePath(filePath)}`
        )
      : path.resolve(
          process.env.STORAGE_DIR,
          `documents/${normalizePath(filePath)}`
        );

      ? path.resolve(
          __dirname,
          `../../storage/documents`,
          normalizePath(filename)
        )
      : path.resolve(
          process.env.STORAGE_DIR,
          `documents`,
          normalizePath(filename)
        );
function normalizePath(filepath = "") {
  return path.normalize(filepath).replace(/^(\.\.(\/|\\|$))+/, "");
}

  normalizePath,
const { purgeVectorCache, purgeSourceDocument, normalizePath } = require(".");
  const folderPath = path.resolve(documentsFolder, normalizePath(folderName));
    .map((file) => path.join(folderPath, file));