From 45ce76061b02e35aeb5ff2eb3ac9e2a2c866d170 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Sun, 1 Mar 2026 16:38:40 -0600 Subject: [PATCH] fix(api): helmet security headers + auth endpoint rate limiting --- apps/api/src/auth/auth.controller.ts | 2 +- apps/api/src/main.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/api/src/auth/auth.controller.ts b/apps/api/src/auth/auth.controller.ts index f0bd96b..b677f48 100644 --- a/apps/api/src/auth/auth.controller.ts +++ b/apps/api/src/auth/auth.controller.ts @@ -106,7 +106,7 @@ export class AuthController { // @SkipCsrf avoids double-protection conflicts. // See: https://www.better-auth.com/docs/reference/security @SkipCsrf() - @Throttle({ strict: { limit: 10, ttl: 60000 } }) + @Throttle({ default: { ttl: 60_000, limit: 5 } }) async handleAuth(@Req() req: ExpressRequest, @Res() res: ExpressResponse): Promise { // Extract client IP for logging const clientIp = this.getClientIp(req); diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index 55dafa1..d55233d 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -1,6 +1,7 @@ import { NestFactory } from "@nestjs/core"; import { RequestMethod, ValidationPipe } from "@nestjs/common"; import cookieParser from "cookie-parser"; +import helmet from "helmet"; import { AppModule } from "./app.module"; import { getTrustedOrigins } from "./auth/auth.config"; import { GlobalExceptionFilter } from "./filters/global-exception.filter"; @@ -33,6 +34,14 @@ async function bootstrap() { // Enable cookie parser for session handling app.use(cookieParser()); + // Enable helmet security headers + app.use( + helmet({ + contentSecurityPolicy: false, // Let Next.js handle CSP + crossOriginEmbedderPolicy: false, + }) + ); + // Enable global validation pipe with transformation app.useGlobalPipes( new ValidationPipe({