CVE-2023-4899 (JavaScript, published 2023-09-12T00:15Z)
Description: value:  SQL Injection in GitHub repository mintplex-labs/anything-llm prior to 0.0.1.
Severity: nan (CVSS v3 base score: 8.8)
Weakness: CWE-89 \u2014 Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
Repository: https://github.com/mintplex-labs/anything-llm
Files changed:
server/endpoints/admin.js
server/endpoints/api/admin/index.js
server/endpoints/api/workspace/index.js
server/endpoints/chat.js
server/endpoints/invite.js
server/endpoints/system.js
server/endpoints/workspaces.js
server/models/invite.js
server/models/user.js
server/models/workspace.js
server/package.json
server/utils/middleware/validApiKey.js
server/yarn.lock
Commit message: patch SQL injection opportunities [LOW RISK] (#234)



Vulnerable code:
          workspaceId,
        const workspace = Workspace.get(`id = ${id}`);
        await Workspace.delete(`id = ${id}`);
        await DocumentVectors.deleteForWorkspace(id);
        await Document.delete(`workspaceId = ${Number(id)}`);
        await WorkspaceChats.delete(`workspaceId = ${Number(id)}`);
        const chats = await WorkspaceChats.whereWithData(`id >= ${offset}`, 20);
          workspaceId,
        const chats = await WorkspaceChats.whereWithData(`id >= ${offset}`, 20);
      const workspace = await Workspace.get(`slug = '${slug}'`);
        const workspace = await Workspace.get(`slug = '${slug}'`);
        await Workspace.delete(`slug = '${slug.toLowerCase()}'`);
        const currWorkspace = await Workspace.get(`slug = '${slug}'`);
        const workspace = await Workspace.get(`slug = '${slug}'`);
        const currWorkspace = await Workspace.get(`slug = '${slug}'`);
        const updatedWorkspace = await Workspace.get(`slug = '${slug}'`);
          ? await Workspace.getWithUser(user, `slug = '${slug}'`)
          : await Workspace.get(`slug = '${slug}'`);
      const invite = await Invite.get(`code = '${code}'`);
      const invite = await Invite.get(`code = '${code}'`);
        const existingUser = await User.get(`username = '${username}'`);
          ? await Workspace.getWithUser(user, `slug = '${slug}'`)
          : await Workspace.get(`slug = '${slug}'`);
          ? await Workspace.getWithUser(user, `slug = '${slug}'`)
          : await Workspace.get(`slug = '${slug}'`);
        const updatedWorkspace = await Workspace.get(`slug = '${slug}'`);
          ? await Workspace.getWithUser(user, `slug = '${slug}'`)
          : await Workspace.get(`slug = '${slug}'`);
        await Workspace.delete(`slug = '${slug.toLowerCase()}'`);
        ? await Workspace.getWithUser(user, `slug = '${slug}'`)
        : await Workspace.get(`slug = '${slug}'`);
          ? await Workspace.getWithUser(user, `slug = '${slug}'`)
          : await Workspace.get(`slug = '${slug}'`);
    const invite = await this.get(`id = ${inviteId}`);
    const invite = await this.get(`id = ${inviteId}`);
    const user = await this.get(`id = ${userId}`);
      const usedUsername = !!(await this.get(`username = '${username}'`));
    const existingBySlug = await this.get(`slug = '${slug}'`);
}
  const apiKey = await ApiKey.get(`secret = '${bearerKey}'`);
  if (!apiKey) {

Fixed code:
const { escape } = require("sqlstring-sqlite");
          escape(Number(workspaceId)),
        const workspace = Workspace.get(`id = ${escape(id)}`);
        await Workspace.delete(`id = ${workspace.id}`);
        await DocumentVectors.deleteForWorkspace(workspace.id);
        await Document.delete(`workspaceId = ${Number(workspace.id)}`);
        await WorkspaceChats.delete(`workspaceId = ${Number(workspace.id)}`);
        const chats = await WorkspaceChats.whereWithData(
          `id >= ${escape(offset)}`,
          20
        );
const { escape } = require("sqlstring-sqlite");
          escape(Number(workspaceId)),
        const chats = await WorkspaceChats.whereWithData(
          `id >= ${escape(offset)}`,
          20
        );
const { escape } = require("sqlstring-sqlite");
      const workspace = await Workspace.get(`slug = ${escape(slug)}`);
        const workspace = await Workspace.get(`slug = ${escape(slug)}`);
        await Workspace.delete(`id = ${Number(workspace.id)}`);
        const currWorkspace = await Workspace.get(`slug = ${escape(slug)}`);
        const workspace = await Workspace.get(`slug = ${escape(slug)}`);
        const currWorkspace = await Workspace.get(`slug = ${escape(slug)}`);
        const updatedWorkspace = await Workspace.get(
          `id = ${Number(currWorkspace.id)}`
        );
const { escape } = require("sqlstring-sqlite");
          ? await Workspace.getWithUser(user, `slug = ${escape(slug)}`)
          : await Workspace.get(`slug = ${escape(slug)}`);
const { escape } = require("sqlstring-sqlite");
      const invite = await Invite.get(`code = ${escape(code)}`);
      const invite = await Invite.get(`code = ${escape(code)}`);
const { escape } = require("sqlstring-sqlite");
        const existingUser = await User.get(`username = ${escape(username)}`);
const { escape } = require("sqlstring-sqlite");
          ? await Workspace.getWithUser(user, `slug = ${escape(slug)}`)
          : await Workspace.get(`slug = ${escape(slug)}`);
          ? await Workspace.getWithUser(user, `slug = ${escape(slug)}`)
          : await Workspace.get(`slug = ${escape(slug)}`);
        const updatedWorkspace = await Workspace.get(
          `id = ${currWorkspace.id}`
        );
          ? await Workspace.getWithUser(user, `slug = ${escape(slug)}`)
          : await Workspace.get(`slug = ${escape(slug)}`);
        await Workspace.delete(`id = ${Number(workspace.id)}`);
        ? await Workspace.getWithUser(user, `slug = ${escape(slug)}`)
        : await Workspace.get(`slug = ${escape(slug)}`);
          ? await Workspace.getWithUser(user, `slug = ${escape(slug)}`)
          : await Workspace.get(`slug = ${escape(slug)}`);
const { escape } = require("sqlstring-sqlite");

    const invite = await this.get(`id = ${escape(inviteId)}`);
    const invite = await this.get(`id = ${escape(inviteId)}`);
const { escape } = require("sqlstring-sqlite");

    const user = await this.get(`id = ${escape(userId)}`);
      const usedUsername = !!(await this.get(`username = ${escape(username)}`));
const { escape } = require("sqlstring-sqlite");
    const existingBySlug = await this.get(`slug = ${escape(slug)}`);
    "sqlstring-sqlite": "^0.1.1",
}
const { escape } = require("sqlstring-sqlite");
  if (!(await ApiKey.get(`secret = ${escape(bearerKey)}`))) {
sqlstring-sqlite@^0.1.1:
  version "0.1.1"
  resolved "https://registry.yarnpkg.com/sqlstring-sqlite/-/sqlstring-sqlite-0.1.1.tgz#c8c61810663f2e59a6b0d737b70a8752bda3a078"
  integrity sha512-9CAYUJ0lEUPYJrswqiqdINNSfq3jqWo/bFJ7tufdoNeSK0Fy+d1kFTxjqO9PIqza0Kri+ZtYMfPVf1aZaFOvrQ==