Fix security and correctness issues found in full-codebase audit
- Restrict meetingPassword field so it isn't leaked via the public REST/GraphQL API - Fix booking slot computation to use Europe/Berlin time instead of the server's UTC clock - Reset email verification when a customer changes their email address - Fix ICS calendar injection via unescaped carriage returns in event descriptions - Bind WebRTC meeting kicks to a persistent client id so they survive a rejoin - Move the meeting signaling token out of the WebSocket query string into the first message - Prevent duplicate signaling connections from leaking when the same participant reconnects - Use the rightmost X-Forwarded-For entry for rate limiting (single trusted reverse proxy) - Use constant-time comparison for the cron endpoint's bearer token - Remove SVG from allowed Media upload types (stored-XSS risk, unused anyway) - Add baseline security headers and a CSP to next.config.ts - Fix CI/CD script injection via unsanitized git ref names in release.yml
This commit is contained in:
+13
-1
@@ -32,7 +32,19 @@ export function checkRateLimit(key: string, opts: { max: number; windowMs: numbe
|
||||
}
|
||||
|
||||
export function getClientIp(request: Request): string {
|
||||
// Deployment is always behind exactly one trusted reverse proxy (see
|
||||
// DEPLOYMENT.md — Nginx Proxy Manager; the app port isn't published
|
||||
// directly to the host). nginx's default `$proxy_add_x_forwarded_for`
|
||||
// *appends* the real client IP to any X-Forwarded-For it already
|
||||
// received rather than replacing it, so a directly-connecting client
|
||||
// could prepend arbitrary spoofed entries of their own. Only the
|
||||
// right-most (last) entry — the one the trusted proxy itself appended —
|
||||
// is trustworthy; taking the first entry would let a client bypass this
|
||||
// rate limit entirely by sending a fake X-Forwarded-For header.
|
||||
const forwarded = request.headers.get("x-forwarded-for");
|
||||
if (forwarded) return forwarded.split(",")[0]!.trim();
|
||||
if (forwarded) {
|
||||
const parts = forwarded.split(",");
|
||||
return parts[parts.length - 1]!.trim();
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user