CVE-2024-1625 (published 2024-04-10T17:15Z)

An Insecure Direct Object Reference (IDOR) vulnerability exists in the lunary-ai/lunary application version 0.3.0, allowing unauthorized deletion of any organization's project. The vulnerability is due to insufficient authorization checks in the project deletion endpoint, where the endpoint fails to verify if the project ID provided in the request belongs to the requesting user's organization. As a result, an attacker can delete projects belonging to any organization by sending a crafted DELETE request with the target project's ID. This issue affects the project deletion functionality implemented in the projects.delete route.


Weakness information:
cwe_id: CWE-863
cwe_name: Incorrect Authorization
description: The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. This allows attackers to bypass intended access restrictions.
extended_description: 
            Assuming a user with a given identity, authorization is the process of determining whether that user can access a given resource, based on the user's privileges and any permissions or other access-control specifications that apply to the resource.
            When access control checks are incorrectly applied, users are able to access data or perform actions that they should not be allowed to perform. This can lead to a wide range of problems, including information exposures, denial of service, and arbitrary code execution.
         
         

Fix information:
repo_url: https://github.com/lunary-ai/lunary
commit_details: repo_url: https://github.com/lunary-ai/lunary
author: hughcrt
author_date: 2024-02-19 09:32:01-03:00
msg: fix: project deletion safeguard
repository: repo_url: https://github.com/lunary-ai/lunary
repo_name: lunary-ai/lunary
description: The production toolkit for LLMs. Observability, prompt management and evaluations. 
repo_language: TypeScript
owner: lunary-ai
file_changes: filename: index.ts
change_type: ModificationType.MODIFY
diff: @@ -1,3 +1,4 @@
+import { verifyProjectAccess } from "@/src/utils/authorization"
 import sql from "@/src/utils/db"
 import Context from "@/src/utils/koa"
 import Router from "koa-router"
@@ -69,7 +70,19 @@ projects.post("/", async (ctx: Context) => {
 
 projects.delete("/:projectId", async (ctx: Context) => {
   const { projectId } = ctx.params
-  const { orgId } = ctx.state
+  const { orgId, userId } = ctx.state
+  console.log(ctx.state)
+
+  const hasProjectAccess = await verifyProjectAccess(projectId, userId)
+  const [user] = await sql`select * from account where id = ${userId}`
+
+  if (!hasProjectAccess) {
+    ctx.throw(401, "Not allowed")
+  }
+
+  if (user.role !== "admin") {
+    ctx.throw(403, "You must be an admin to delete a project")
+  }
 
   const [{ count }] =
     await sql`select count(*)::int from  project where org_id = ${orgId}`
@@ -77,6 +90,7 @@ projects.delete("/:projectId", async (ctx: Context) => {
   if (count > 1) {
     await sql`delete from project where id = ${projectId}`
     ctx.status = 200
+    ctx.body = {}
   } else {
     ctx.status = 422
 

programming_language: TypeScript
filename: authorization.ts
change_type: ModificationType.ADD
diff: @@ -0,0 +1,13 @@
+import sql from "./db"
+
+export async function verifyProjectAccess(projectId: string, userId: string) {
+  const [{ exists: hasAccess }] = await sql`
+      select exists (
+        select 1 
+        from project 
+        where org_id = (select org_id from account where id = ${userId}) 
+          and id = ${projectId}
+      )
+    `
+  return hasAccess
+}

programming_language: TypeScript