fix(rateLimit): return loopback ip in development to keep rate limiting active

- use `127.0.0.1` as fallback ip when `NODE_ENV === 'development'` in both `getIpFromHeaders` and `getIpFromRequest`
- preserve `unknown` fallback in production to suspend rate limiting when no trusted proxy is configured
- update comments to reflect environment-specific behaviour
This commit is contained in:
2026-04-24 21:38:27 -04:00
parent 879fee1b80
commit 238666f9cc
+6 -6
View File
@@ -122,12 +122,12 @@ export function getIpFromHeaders(headersList) {
const realIp = headersList.get('x-real-ip')?.trim(); const realIp = headersList.get('x-real-ip')?.trim();
if (realIp && isValidIp(realIp)) return realIp; if (realIp && isValidIp(realIp)) return realIp;
} }
// Fallback when no trusted proxy is configured. // In development, use loopback so rate limiting stays active and the
// Callers (router.js, authActions.js) treat 'unknown' as a signal to suspend // "IP cannot be determined" warning is not emitted.
// rate limiting rather than collapse all traffic into one shared bucket — which // In production without a trusted proxy, return 'unknown' to suspend rate
// would allow a single attacker to exhaust the quota and deny service globally. // limiting rather than collapse all traffic into one shared bucket.
// Configure ZEN_TRUST_PROXY=true behind a verified reverse proxy. // Configure ZEN_TRUST_PROXY=true behind a verified reverse proxy.
return 'unknown'; return process.env.NODE_ENV === 'development' ? '127.0.0.1' : 'unknown';
} }
/** /**
@@ -143,7 +143,7 @@ export function getIpFromRequest(request) {
const realIp = request.headers.get('x-real-ip')?.trim(); const realIp = request.headers.get('x-real-ip')?.trim();
if (realIp && isValidIp(realIp)) return realIp; if (realIp && isValidIp(realIp)) return realIp;
} }
return 'unknown'; return process.env.NODE_ENV === 'development' ? '127.0.0.1' : 'unknown';
} }
/** /**