diff --git a/src/middleware.js b/src/middleware.js index 7bc6221..1e98e5c 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -6,11 +6,16 @@ const webhookRateLimiter = new RateLimiter({ maxRequests: 100, windowMs: 60 * 10 const apiRateLimiter = new RateLimiter({ maxRequests: 60, windowMs: 60 * 1000 }); const keyBackupRateLimiter = new RateLimiter({ maxRequests: 5, windowMs: 60 * 60 * 1000 }); -function getClientIp(request) { +export function readTrustedProxyCount(value = process.env.TRUSTED_PROXY_COUNT) { + const parsed = Number(value ?? 0); + return Number.isInteger(parsed) && parsed > 0 ? parsed : 0; +} + +export function getClientIp(request) { // See the detailed note in src/lib/server/rate-limiter.js. // X-Forwarded-For is user-controllable unless a trusted proxy strips/rewrites it. // Honour TRUSTED_PROXY_COUNT when set; otherwise fall back to X-Real-IP only. - const trustedProxyCount = parseInt(process.env.TRUSTED_PROXY_COUNT ?? '0', 10); + const trustedProxyCount = readTrustedProxyCount(); if (trustedProxyCount > 0) { const xff = request.headers.get('x-forwarded-for'); diff --git a/tests/middleware-trusted-proxy.test.js b/tests/middleware-trusted-proxy.test.js new file mode 100644 index 0000000..1673601 --- /dev/null +++ b/tests/middleware-trusted-proxy.test.js @@ -0,0 +1,37 @@ +import { describe, expect, it } from 'vitest'; +import { getClientIp, readTrustedProxyCount } from '../src/middleware.js'; + +function requestWithHeaders(headers) { + return { + headers: { + get(name) { + return headers[name.toLowerCase()] ?? null; + } + } + }; +} + +describe('middleware trusted proxy count', () => { + it('ignores malformed TRUSTED_PROXY_COUNT values', () => { + expect(readTrustedProxyCount('2abc')).toBe(0); + expect(readTrustedProxyCount('1.5')).toBe(0); + expect(readTrustedProxyCount('-1')).toBe(0); + expect(readTrustedProxyCount('2')).toBe(2); + }); + + it('falls back to x-real-ip when TRUSTED_PROXY_COUNT is malformed', () => { + const previous = process.env.TRUSTED_PROXY_COUNT; + process.env.TRUSTED_PROXY_COUNT = '1abc'; + + expect( + getClientIp( + requestWithHeaders({ + 'x-forwarded-for': '203.0.113.10, 198.51.100.20', + 'x-real-ip': '198.51.100.99' + }) + ) + ).toBe('198.51.100.99'); + + process.env.TRUSTED_PROXY_COUNT = previous; + }); +});