From 97cfd0ed90a1d9b023263ab6fb597d63a0fa3888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Thu, 9 Apr 2026 21:48:51 +0200 Subject: [PATCH] fix(security): raise password minimum to 12 chars, hide raw error messages, add audit script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Password validation: min(8) → min(12) across auth.ts, user-procedure-support.ts, and invite.ts (aligns with NIST SP 800-63B modern recommendations) - Error boundary: stop rendering raw error.message which could leak internal details; always show the generic fallback text - Add `pnpm audit` script (--audit-level=high) for dependency vulnerability scanning Co-Authored-By: Claude Sonnet 4.6 --- apps/web/src/app/(app)/error.tsx | 2 +- package.json | 1 + packages/api/src/router/auth.ts | 2 +- packages/api/src/router/invite.ts | 2 +- packages/api/src/router/user-procedure-support.ts | 4 ++-- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/web/src/app/(app)/error.tsx b/apps/web/src/app/(app)/error.tsx index a617ee1..984482c 100644 --- a/apps/web/src/app/(app)/error.tsx +++ b/apps/web/src/app/(app)/error.tsx @@ -34,7 +34,7 @@ export default function AppError({ Something went wrong

- {error.message || "An unexpected error occurred. The team has been notified."} + {"An unexpected error occurred. The team has been notified."}

{error.digest && (

diff --git a/package.json b/package.json index d3db5ce..7015464 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "test:e2e": "node ./scripts/run-from-workspace-root.mjs turbo test:e2e", "test:e2e:email": "pnpm --filter @capakraken/web test:e2e:email", "test:scripts": "node --test scripts/*.test.mjs", + "audit": "pnpm audit --audit-level=high", "check:architecture": "node ./scripts/check-architecture-guardrails.mjs", "check:exports": "node ./scripts/check-workspace-exports.mjs", "check:imports": "node ./scripts/check-workspace-imports.mjs", diff --git a/packages/api/src/router/auth.ts b/packages/api/src/router/auth.ts index 93ba61c..efec654 100644 --- a/packages/api/src/router/auth.ts +++ b/packages/api/src/router/auth.ts @@ -74,7 +74,7 @@ export const authRouter = createTRPCRouter({ .input( z.object({ token: z.string().min(1), - password: z.string().min(8, "Password must be at least 8 characters."), + password: z.string().min(12, "Password must be at least 12 characters."), }), ) .mutation(async ({ ctx, input }) => { diff --git a/packages/api/src/router/invite.ts b/packages/api/src/router/invite.ts index acb66f5..55c4b5a 100644 --- a/packages/api/src/router/invite.ts +++ b/packages/api/src/router/invite.ts @@ -109,7 +109,7 @@ export const inviteRouter = createTRPCRouter({ .input( z.object({ token: z.string(), - password: z.string().min(8, "Password must be at least 8 characters."), + password: z.string().min(12, "Password must be at least 12 characters."), }), ) .mutation(async ({ ctx, input }) => { diff --git a/packages/api/src/router/user-procedure-support.ts b/packages/api/src/router/user-procedure-support.ts index 8685ae6..f0a5954 100644 --- a/packages/api/src/router/user-procedure-support.ts +++ b/packages/api/src/router/user-procedure-support.ts @@ -10,12 +10,12 @@ export const CreateUserInputSchema = z.object({ email: z.string().email(), name: z.string().min(1), systemRole: z.nativeEnum(SystemRole).default(SystemRole.USER), - password: z.string().min(8), + password: z.string().min(12), }); export const SetUserPasswordInputSchema = z.object({ userId: z.string(), - password: z.string().min(8, "Password must be at least 8 characters"), + password: z.string().min(12, "Password must be at least 12 characters"), }); export const UpdateUserRoleInputSchema = z.object({