fix(security): harden owner pair-code against brute-force

- Set express trust proxy=1 so req.ip is the real client (one Dokku
  nginx hop). Drop the X-Forwarded-For fallback — it was client-spoofable.
- Add a global redeem rate limit (30/min across all IPs) so rotating
  proxies can't outpace the per-IP limiter.
- Every failed redeem now decrements life from all active pair codes
  via a shared failures counter. After 5 wrong guesses during a code's
  5-minute TTL, the owner's real code gets burned and they must re-mint.
  This makes the 20-bit entropy of a 6-digit code defensible: an
  attacker doesn't know which code is real and can't probe long enough
  to find it before triggering the burn.
This commit is contained in:
2026-06-01 10:16:30 +01:00
parent 90a4459e63
commit 36118b4a4f
2 changed files with 55 additions and 13 deletions
+5
View File
@@ -17,6 +17,11 @@ import { createOptionalAuth } from './lib/auth.js';
const app = express();
// We sit behind one Nginx hop (Dokku's per-app vhost). Trust exactly one
// proxy so req.ip reflects the real client and the rate limiters below
// can't be bypassed via a spoofed X-Forwarded-For header.
app.set('trust proxy', 1);
app.use(helmet({ contentSecurityPolicy: false }));
app.use(cors({ origin: env.appUrl, credentials: true }));
app.use(express.json({ limit: '2mb' }));