CVE-2024-3104: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') (CWE-78)
value: A remote code execution vulnerability exists in mintplex-labs/anything-llm due to improper handling of environment variables. Attackers can exploit this vulnerability by injecting arbitrary environment variables via the `POST /api/system/update-env` endpoint, which allows for the execution of arbitrary code on the host running anything-llm. The vulnerability is present in the latest version of anything-llm, with the latest commit identified as fde905aac1812b84066ff72e5f2f90b56d4c3a59. This issue has been fixed in version 1.0.0. Successful exploitation could lead to code execution on the host, enabling attackers to read and modify data accessible to the user running the service, potentially leading to a denial of service. 
CWE description: The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
Published: 2024-06-06T18:15Z
Repository: https://github.com/mintplex-labs/anything-llm
Language: JavaScript
Files changed: server/utils/helpers/updateENV.js
Commit date: 2024-03-29 13:03:05 -0700
Commit message: security: force sanitize env string set by user

Diff: diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js
index 29fa210ef..6e0e5daa6 100644
--- a/server/utils/helpers/updateENV.js
+++ b/server/utils/helpers/updateENV.js
@@ -562,21 +562,29 @@ async function dumpENV() {
     "HTTPS_KEY_PATH",
     // DISABLED TELEMETRY
     "DISABLE_TELEMETRY",
   ];
 
+  // Simple sanitization of each value to prevent ENV injection via newline or quote escaping.
+  function sanitizeValue(value) {
+    const offendingChars =
+      /[\n\r\t\v\f\u0085\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000"'`#]/;
+    const firstOffendingCharIndex = value.search(offendingChars);
+    if (firstOffendingCharIndex === -1) return value;
+
+    return value.substring(0, firstOffendingCharIndex);
+  }
+
   for (const key of protectedKeys) {
     const envValue = process.env?.[key] || null;
     if (!envValue) continue;
     frozenEnvs[key] = process.env?.[key] || null;
   }
 
   var envResult = `# Auto-dump ENV from system call on ${new Date().toTimeString()}\n`;
   envResult += Object.entries(frozenEnvs)
-    .map(([key, value]) => {
-      return `${key}='${value}'`;
-    })
+    .map(([key, value]) => `${key}='${sanitizeValue(value)}'`)
     .join("\n");
 
   const envPath = path.join(__dirname, "../../.env");
   fs.writeFileSync(envPath, envResult, { encoding: "utf8", flag: "w" });
   return true;

Vulnerable code:     .map(([key, value]) => {
      return `${key}='${value}'`;
    })
Fixed code:   // Simple sanitization of each value to prevent ENV injection via newline or quote escaping.
  function sanitizeValue(value) {
    const offendingChars =
      /[\n\r\t\v\f\u0085\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000"'`#]/;
    const firstOffendingCharIndex = value.search(offendingChars);
    if (firstOffendingCharIndex === -1) return value;

    return value.substring(0, firstOffendingCharIndex);
  }

    .map(([key, value]) => `${key}='${sanitizeValue(value)}'`)