From 90dfe65fa396f9426fc86905a0b259560456b536 Mon Sep 17 00:00:00 2001 From: MOHAN Date: Wed, 26 Aug 2026 20:49:45 +0530 Subject: [PATCH] Trust the reverse proxy for real client IP resolution Without Express's trust-proxy setting, req.ip resolves to the load balancer's own connecting IP for every request in production, not the real client IP. That silently broke per-IP rate limiting: every user behind the same proxy shared one 100-requests-per-60-seconds throttler bucket instead of getting their own, so any real traffic volume (the dashboard alone fires ~6 requests per load) could 429 everyone, including on login/registration. --- src/main.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main.ts b/src/main.ts index 7b0b373..6cf8076 100644 --- a/src/main.ts +++ b/src/main.ts @@ -25,6 +25,16 @@ async function bootstrap() { rawBody: true, // Required for Stripe webhook signature verification }); + // ─── Trust the reverse proxy / load balancer in front of this app ───────── + // Without this, Express's req.ip (and therefore per-IP rate limiting) sees + // the proxy's own connecting IP for every request instead of the real + // client IP, so every user behind the same proxy shares one rate-limit + // bucket. Only relevant in production, where a proxy is expected; in local + // dev the app is hit directly. + if (isProduction) { + app.getHttpAdapter().getInstance().set("trust proxy", 1); + } + // ─── Security headers ───────────────────────────────────────────────────── const scriptSrc = isProduction ? ["'self'"] : ["'self'", "'unsafe-inline'"]; const styleSrc = isProduction ? ["'self'"] : ["'self'", "'unsafe-inline'"];