CVE-2023-4897 (published 2023-09-11T21:15Z)

Relative Path Traversal in GitHub repository mintplex-labs/anything-llm prior to 0.0.1.

CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-23
cwe_name: Relative Path Traversal
description: 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.
extended_description: This allows attackers to traverse the file system to access files or directories that are outside of the restricted directory.
         

Fix information:
repo_url: https://github.com/mintplex-labs/anything-llm
commit_details: repo_url: https://github.com/mintplex-labs/anything-llm
author: Timothy Carambat
author_date: 2023-09-11 22:07:48+02:00
msg: prevent exports path traversal (#233)
repository: repo_url: https://github.com/mintplex-labs/anything-llm
repo_name: Mintplex-Labs/anything-llm
description: The all-in-one Desktop & Docker AI application with full RAG and AI Agent capabilities.
repo_language: JavaScript
owner: mintplex-labs
file_changes: filename: index.jsx
change_type: ModificationType.MODIFY
diff: @@ -177,8 +177,9 @@ export default function DocumentSettings({ workspace }) {
         </div>
       </div>
       <div
-        className={`flex items-center ${canDelete ? "justify-between" : "justify-end"
-          } p-4 md:p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600`}
+        className={`flex items-center ${
+          canDelete ? "justify-between" : "justify-end"
+        } p-4 md:p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600`}
       >
         <button
           hidden={!canDelete}

programming_language: TypeScript
filename: system.js
change_type: ModificationType.MODIFY
diff: @@ -24,6 +24,7 @@ const { User } = require("../models/user");
 const { validatedRequest } = require("../utils/middleware/validatedRequest");
 const { handleImports } = setupDataImports();
 const { handleLogoUploads } = setupLogoUploads();
+const fs = require("fs");
 const path = require("path");
 const {
   getDefaultFilename,
@@ -315,9 +316,21 @@ function systemEndpoints(app) {
     "/system/data-exports/:filename",
     [validatedRequest],
     (request, response) => {
-      const filePath =
-        __dirname + "/../storage/exports/" + request.params.filename;
-      response.download(filePath, request.params.filename, (err) => {
+      const exportLocation = __dirname + "/../storage/exports/";
+      const sanitized = path
+        .normalize(request.params.filename)
+        .replace(/^(\.\.(\/|\\|$))+/, "");
+      const finalDestination = path.join(exportLocation, sanitized);
+
+      if (!fs.existsSync(finalDestination)) {
+        response.status(404).json({
+          error: 404,
+          msg: `File ${request.params.filename} does not exist in exports.`,
+        });
+        return;
+      }
+
+      response.download(finalDestination, request.params.filename, (err) => {
         if (err) {
           response.send({
             error: err,
@@ -448,13 +461,11 @@ function systemEndpoints(app) {
         response.status(200).json({ canDelete });
       } catch (error) {
         console.error("Error fetching can delete workspaces:", error);
-        response
-          .status(500)
-          .json({
-            success: false,
-            message: "Internal server error",
-            canDelete: false,
-          });
+        response.status(500).json({
+          success: false,
+          message: "Internal server error",
+          canDelete: false,
+        });
       }
     }
   );

programming_language: JavaScript