CVE-2024-5216: Insufficient Information (NVD-CWE-noinfo)
value: A vulnerability in mintplex-labs/anything-llm allows for a Denial of Service (DoS) condition due to uncontrolled resource consumption. Specifically, the issue arises from the application's failure to limit the size of usernames, enabling attackers to create users with excessively bulky texts in the username field. This exploit results in the user management panel becoming unresponsive, preventing administrators from performing critical user management actions such as editing, suspending, or deleting users. The impact of this vulnerability includes administrative paralysis, compromised security, and operational disruption, as it allows malicious users to perpetuate their presence within the system indefinitely, undermines the system's security posture, and degrades overall system performance.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-06-25T11:15Z
Repository: https://github.com/mintplex-labs/anything-llm
Language: JavaScript
Files changed: server/endpoints/system.js, server/models/user.js
Commit date: 2024-05-22 13:21:26 -0500
Commit message: enfore min and max username lengths to prevent DOS via spam-length names

Diff: diff --git a/server/endpoints/system.js b/server/endpoints/system.js
index f4057a404..6c941b1cc 100644
--- a/server/endpoints/system.js
+++ b/server/endpoints/system.js
@@ -1022,11 +1022,11 @@ function systemEndpoints(app) {
         return;
       }
 
       const updates = {};
       if (username) {
-        updates.username = String(username);
+        updates.username = User.validations.username(String(username));
       }
       if (password) {
         updates.password = String(password);
       }
 
diff --git a/server/models/user.js b/server/models/user.js
index a1aeb2c63..f08548afb 100644
--- a/server/models/user.js
+++ b/server/models/user.js
@@ -8,10 +8,24 @@ const User = {
     "password",
     "pfpFilename",
     "role",
     "suspended",
   ],
+  validations: {
+    username: (newValue = "") => {
+      try {
+        if (String(newValue).length > 100)
+          throw new Error("Username cannot be longer than 100 characters");
+        if (String(newValue).length < 2)
+          throw new Error("Username must be at least 2 characters");
+        return String(newValue);
+      } catch (e) {
+        throw new Error(e.message);
+      }
+    },
+  },
+
   // validations for the above writable fields.
   castColumnValue: function (key, value) {
     switch (key) {
       case "suspended":
         return Number(Boolean(value));
@@ -34,13 +48,13 @@ const User = {
     try {
       const bcrypt = require("bcrypt");
       const hashedPassword = bcrypt.hashSync(password, 10);
       const user = await prisma.users.create({
         data: {
-          username,
+          username: this.validations.username(username),
           password: hashedPassword,
-          role,
+          role: String(role),
         },
       });
       return { user: this.filterFields(user), error: null };
     } catch (error) {
       console.error("FAILED TO CREATE USER.", error.message);
@@ -73,11 +87,17 @@ const User = {
 
       // Removes non-writable fields for generic updates
       // and force-casts to the proper type;
       Object.entries(updates).forEach(([key, value]) => {
         if (this.writable.includes(key)) {
-          updates[key] = this.castColumnValue(key, value);
+          if (this.validations.hasOwnProperty(key)) {
+            updates[key] = this.validations[key](
+              this.castColumnValue(key, value)
+            );
+          } else {
+            updates[key] = this.castColumnValue(key, value);
+          }
           return;
         }
         delete updates[key];
       });
 

Vulnerable code:         updates.username = String(username);
          username,
          role,
          updates[key] = this.castColumnValue(key, value);
Fixed code:         updates.username = User.validations.username(String(username));
  validations: {
    username: (newValue = "") => {
      try {
        if (String(newValue).length > 100)
          throw new Error("Username cannot be longer than 100 characters");
        if (String(newValue).length < 2)
          throw new Error("Username must be at least 2 characters");
        return String(newValue);
      } catch (e) {
        throw new Error(e.message);
      }
    },
  },

          username: this.validations.username(username),
          role: String(role),
          if (this.validations.hasOwnProperty(key)) {
            updates[key] = this.validations[key](
              this.castColumnValue(key, value)
            );
          } else {
            updates[key] = this.castColumnValue(key, value);
          }