diff --git a/apps/api/src/config/proxy.ts b/apps/api/src/config/proxy.ts index c520b50..ef6f086 100644 --- a/apps/api/src/config/proxy.ts +++ b/apps/api/src/config/proxy.ts @@ -6,7 +6,13 @@ export function resolveTrustProxy(raw = process.env['TRUST_PROXY']): TrustProxy const value = raw?.trim() if (!value || value.toLowerCase() === 'false') return false if (value.toLowerCase() === 'true') return true - if (/^\d+$/.test(value)) return Number(value) + if (/^\d+$/.test(value)) { + // Hop-count-only trust can't validate the immediate peer, so @fastify/proxy-addr + // no longer supports it (it always fails closed). The only documented deployment + // puts the reverse proxy on the same host, forwarding to loopback, so treat a + // numeric value as "trust the loopback interface" to keep TRUST_PROXY=1 working. + return ['127.0.0.1', '::1'] + } const addresses = value.split(',').map((address) => address.trim()).filter(Boolean) if (addresses.length === 0) return false return addresses.length === 1 ? addresses[0]! : addresses diff --git a/apps/api/test/rate-limit.test.ts b/apps/api/test/rate-limit.test.ts index dde0dd6..f300762 100644 --- a/apps/api/test/rate-limit.test.ts +++ b/apps/api/test/rate-limit.test.ts @@ -35,7 +35,7 @@ describe('rate limit isolation and proxy handling', () => { it('parses explicit trust proxy settings safely', () => { assert.equal(resolveTrustProxy(''), false) assert.equal(resolveTrustProxy('false'), false) - assert.equal(resolveTrustProxy('1'), 1) + assert.deepEqual(resolveTrustProxy('1'), ['127.0.0.1', '::1']) assert.deepEqual(resolveTrustProxy('127.0.0.1, ::1'), ['127.0.0.1', '::1']) })