From 78f9c47dfd8870238b8349b65756aeb74f6db01d Mon Sep 17 00:00:00 2001 From: ogzhanolguncu Date: Fri, 6 Dec 2024 22:24:15 +0300 Subject: [PATCH 1/3] fix: keys setting vulns --- .../app/(app)/apis/[apiId]/settings/default-bytes.tsx | 4 ---- .../app/(app)/apis/[apiId]/settings/default-prefix.tsx | 5 +---- apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts | 3 +-- apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts | 3 +-- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/apps/dashboard/app/(app)/apis/[apiId]/settings/default-bytes.tsx b/apps/dashboard/app/(app)/apis/[apiId]/settings/default-bytes.tsx index 995d3b6572..92a7b7f77a 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/settings/default-bytes.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/settings/default-bytes.tsx @@ -19,7 +19,6 @@ import { useForm } from "react-hook-form"; import { z } from "zod"; const formSchema = z.object({ keyAuthId: z.string(), - workspaceId: z.string(), defaultBytes: z .number() .min(8, "Byte size needs to be at least 8") @@ -30,7 +29,6 @@ const formSchema = z.object({ type Props = { keyAuth: { id: string; - workspaceId: string; defaultBytes: number | undefined | null; }; }; @@ -42,7 +40,6 @@ export const DefaultBytes: React.FC = ({ keyAuth }) => { defaultValues: { defaultBytes: keyAuth.defaultBytes ?? undefined, keyAuthId: keyAuth.id, - workspaceId: keyAuth.workspaceId, }, }); @@ -78,7 +75,6 @@ export const DefaultBytes: React.FC = ({ keyAuth }) => {
- = ({ keyAuth }) => { defaultValues: { defaultPrefix: keyAuth.defaultPrefix ?? undefined, keyAuthId: keyAuth.id, - workspaceId: keyAuth.workspaceId, }, }); @@ -71,7 +69,6 @@ export const DefaultPrefix: React.FC = ({ keyAuth }) => {
- { @@ -30,7 +29,7 @@ export const setDefaultApiBytes = t.procedure "We were unable to find the KeyAuth. Please try again or contact support@unkey.dev.", }); }); - if (!keyAuth || keyAuth.workspaceId !== input.workspaceId) { + if (!keyAuth) { throw new TRPCError({ code: "NOT_FOUND", message: diff --git a/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts b/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts index b28406dc8e..3913dc69b9 100644 --- a/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts +++ b/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts @@ -11,7 +11,6 @@ export const setDefaultApiPrefix = t.procedure z.object({ defaultPrefix: z.string().max(8, "Prefix can be a maximum of 8 characters"), keyAuthId: z.string(), - workspaceId: z.string(), }), ) .mutation(async ({ ctx, input }) => { @@ -25,7 +24,7 @@ export const setDefaultApiPrefix = t.procedure message: "We were unable to find KeyAuth. Please try again or contact support@unkey.dev.", }); }); - if (!keyAuth || keyAuth.workspaceId !== input.workspaceId) { + if (!keyAuth) { throw new TRPCError({ code: "NOT_FOUND", message: From 0c51ab136cec7ce424b57fe5c7d2667c1eca9dcd Mon Sep 17 00:00:00 2001 From: chronark Date: Fri, 6 Dec 2024 20:44:45 +0100 Subject: [PATCH 2/3] fix: check workspace ownership --- .../lib/trpc/routers/api/setDefaultBytes.ts | 23 ++++++++++++---- .../lib/trpc/routers/api/setDefaultPrefix.ts | 27 ++++++++++++++----- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts b/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts index 7435cfd152..e2dbcb5161 100644 --- a/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts +++ b/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts @@ -18,9 +18,14 @@ export const setDefaultApiBytes = t.procedure }), ) .mutation(async ({ ctx, input }) => { - const keyAuth = await db.query.keyAuth + const workspace = await db.query.workspaces .findFirst({ - where: (table, { eq }) => eq(table.id, input.keyAuthId), + where: (table, { eq }) => eq(table.tenantId, ctx.tenant.id), + with: { + keySpaces: { + where: (table, { eq }) => eq(table.id, input.keyAuthId), + }, + }, }) .catch((_err) => { throw new TRPCError({ @@ -29,6 +34,14 @@ export const setDefaultApiBytes = t.procedure "We were unable to find the KeyAuth. Please try again or contact support@unkey.dev.", }); }); + if (!workspace) { + throw new TRPCError({ + code: "NOT_FOUND", + message: + "We are unable to find the correct workspace. Please try again or contact support@unkey.dev", + }); + } + const keyAuth = workspace.keySpaces.at(0); if (!keyAuth) { throw new TRPCError({ code: "NOT_FOUND", @@ -43,7 +56,7 @@ export const setDefaultApiBytes = t.procedure .set({ defaultBytes: input.defaultBytes, }) - .where(eq(schema.keyAuth.id, input.keyAuthId)) + .where(eq(schema.keyAuth.id, keyAuth.id)) .catch((_err) => { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", @@ -52,13 +65,13 @@ export const setDefaultApiBytes = t.procedure }); }); await insertAuditLogs(tx, { - workspaceId: keyAuth.workspaceId, + workspaceId: workspace.id, actor: { type: "user", id: ctx.user.id, }, event: "api.update", - description: `Changed ${keyAuth.workspaceId} default byte size for keys from ${keyAuth.defaultBytes} to ${input.defaultBytes}`, + description: `Changed ${keyAuth.id} default byte size for keys from ${keyAuth.defaultBytes} to ${input.defaultBytes}`, resources: [ { type: "keyAuth", diff --git a/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts b/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts index 3913dc69b9..8460a7d3f3 100644 --- a/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts +++ b/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts @@ -14,16 +14,30 @@ export const setDefaultApiPrefix = t.procedure }), ) .mutation(async ({ ctx, input }) => { - const keyAuth = await db.query.keyAuth + const workspace = await db.query.workspaces .findFirst({ - where: (table, { eq }) => eq(table.id, input.keyAuthId), + where: (table, { eq }) => eq(table.tenantId, ctx.tenant.id), + with: { + keySpaces: { + where: (table, { eq }) => eq(table.id, input.keyAuthId), + }, + }, }) .catch((_err) => { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", - message: "We were unable to find KeyAuth. Please try again or contact support@unkey.dev.", + message: + "We were unable to find the KeyAuth. Please try again or contact support@unkey.dev.", }); }); + if (!workspace) { + throw new TRPCError({ + code: "NOT_FOUND", + message: + "We are unable to find the correct workspace. Please try again or contact support@unkey.dev", + }); + } + const keyAuth = workspace.keySpaces.at(0); if (!keyAuth) { throw new TRPCError({ code: "NOT_FOUND", @@ -31,6 +45,7 @@ export const setDefaultApiPrefix = t.procedure "We are unable to find the correct keyAuth. Please try again or contact support@unkey.dev", }); } + await db .transaction(async (tx) => { await tx @@ -38,7 +53,7 @@ export const setDefaultApiPrefix = t.procedure .set({ defaultPrefix: input.defaultPrefix, }) - .where(eq(schema.keyAuth.id, input.keyAuthId)) + .where(eq(schema.keyAuth.id, keyAuth.id)) .catch((_err) => { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", @@ -47,13 +62,13 @@ export const setDefaultApiPrefix = t.procedure }); }); await insertAuditLogs(tx, { - workspaceId: keyAuth.workspaceId, + workspaceId: workspace.id, actor: { type: "user", id: ctx.user.id, }, event: "api.update", - description: `Changed ${keyAuth.workspaceId} default prefix from ${keyAuth.defaultPrefix} to ${input.defaultPrefix}`, + description: `Changed ${keyAuth.id} default prefix from ${keyAuth.defaultPrefix} to ${input.defaultPrefix}`, resources: [ { type: "keyAuth", From b1ed43c031c1d3ff1e269ba867f59ac076ca1903 Mon Sep 17 00:00:00 2001 From: chronark Date: Fri, 6 Dec 2024 20:49:09 +0100 Subject: [PATCH 3/3] fix: check workspace ownership --- .../lib/trpc/routers/api/setDefaultBytes.ts | 25 ++++++------------- .../lib/trpc/routers/api/setDefaultPrefix.ts | 25 ++++++------------- 2 files changed, 16 insertions(+), 34 deletions(-) diff --git a/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts b/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts index e2dbcb5161..82d0ffb3e1 100644 --- a/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts +++ b/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts @@ -18,35 +18,26 @@ export const setDefaultApiBytes = t.procedure }), ) .mutation(async ({ ctx, input }) => { - const workspace = await db.query.workspaces + const keyAuth = await db.query.keyAuth .findFirst({ - where: (table, { eq }) => eq(table.tenantId, ctx.tenant.id), + where: (table, { eq, and, isNull }) => + and(eq(table.id, input.keyAuthId), isNull(table.deletedAt)), with: { - keySpaces: { - where: (table, { eq }) => eq(table.id, input.keyAuthId), - }, + workspace: true, }, }) .catch((_err) => { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: - "We were unable to find the KeyAuth. Please try again or contact support@unkey.dev.", + "We were unable to update the key auth. Please try again or contact support@unkey.dev", }); }); - if (!workspace) { - throw new TRPCError({ - code: "NOT_FOUND", - message: - "We are unable to find the correct workspace. Please try again or contact support@unkey.dev", - }); - } - const keyAuth = workspace.keySpaces.at(0); - if (!keyAuth) { + if (!keyAuth || keyAuth.workspace.tenantId !== ctx.tenant.id) { throw new TRPCError({ code: "NOT_FOUND", message: - "We are unable to find the correct keyAuth. Please try again or contact support@unkey.dev", + "We are unable to find the correct key auth. Please try again or contact support@unkey.dev.", }); } await db @@ -65,7 +56,7 @@ export const setDefaultApiBytes = t.procedure }); }); await insertAuditLogs(tx, { - workspaceId: workspace.id, + workspaceId: keyAuth.workspace.id, actor: { type: "user", id: ctx.user.id, diff --git a/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts b/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts index 8460a7d3f3..d5f6feeeae 100644 --- a/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts +++ b/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts @@ -14,35 +14,26 @@ export const setDefaultApiPrefix = t.procedure }), ) .mutation(async ({ ctx, input }) => { - const workspace = await db.query.workspaces + const keyAuth = await db.query.keyAuth .findFirst({ - where: (table, { eq }) => eq(table.tenantId, ctx.tenant.id), + where: (table, { eq, and, isNull }) => + and(eq(table.id, input.keyAuthId), isNull(table.deletedAt)), with: { - keySpaces: { - where: (table, { eq }) => eq(table.id, input.keyAuthId), - }, + workspace: true, }, }) .catch((_err) => { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: - "We were unable to find the KeyAuth. Please try again or contact support@unkey.dev.", + "We were unable to update the key auth. Please try again or contact support@unkey.dev", }); }); - if (!workspace) { - throw new TRPCError({ - code: "NOT_FOUND", - message: - "We are unable to find the correct workspace. Please try again or contact support@unkey.dev", - }); - } - const keyAuth = workspace.keySpaces.at(0); - if (!keyAuth) { + if (!keyAuth || keyAuth.workspace.tenantId !== ctx.tenant.id) { throw new TRPCError({ code: "NOT_FOUND", message: - "We are unable to find the correct keyAuth. Please try again or contact support@unkey.dev", + "We are unable to find the correct key auth. Please try again or contact support@unkey.dev.", }); } @@ -62,7 +53,7 @@ export const setDefaultApiPrefix = t.procedure }); }); await insertAuditLogs(tx, { - workspaceId: workspace.id, + workspaceId: keyAuth.workspace.id, actor: { type: "user", id: ctx.user.id,