fix(server): resilient rate-limit key + narrower trustProxy for reverse-proxy setups#1303
Merged
steilerDev merged 1 commit intobetafrom Apr 19, 2026
Merged
Conversation
…se-proxy setups Two production fixes triggered by the fastify 5.8.5 security patch for CVE-2026-33806 (trustProxy socketAddr null-check). Under the tightened code path, `request.ip` can resolve to `undefined` when the raw TCP socket lacks metadata, which collapses `@fastify/rate-limit`'s default `keyGenerator` (which uses `request.ip`) to a single `undefined` bucket — effectively shared across all unknown-IP callers. Changes: - `server/src/plugins/rateLimitPlugin.ts`: add explicit keyGenerator that falls back through `request.ip` → first x-forwarded-for → x-real-ip → literal "unknown". Unknown-IP requests are still rate-limited (bucketed as "unknown") rather than silently shared. - `server/src/app.ts`: pass `trustProxy: 1` (number of hops) instead of boolean `true`. We sit behind exactly one reverse proxy in production; the number-based path is the more precise and robust semantic, and it's the code path explicitly restored/hardened in 5.8.5 per the CVE advisory. Public `/api/config` still exposes `trustProxy` as boolean — the external contract is unchanged. Only the Fastify constructor arg is narrowed. Unblocks PR #1215 (beta → main promotion) E2E Gates by fixing the `proxy-setup.spec.ts:186` X-Forwarded-For regression. Co-Authored-By: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com>
Contributor
|
Thank you for your submission! We require all contributors to sign our Contributor License Agreement before we can accept your contribution. I have read the CLA Document and I hereby sign the CLA Frank Steiler seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two production fixes triggered by the fastify 5.8.5 security patch for CVE-2026-33806 (trustProxy socketAddr null-check). Under the tightened code path,
request.ipcan resolve toundefinedwhen the raw TCP socket lacks metadata — collapsing@fastify/rate-limit's default keyGenerator (which usesrequest.ip) to a singleundefinedbucket shared across all unknown-IP callers. This triggers the loginmax: 20bucket after 20 requests and returns 429s to all subsequent callers.Changes:
rateLimitPlugin.ts: add explicitkeyGeneratorwith fallback chainrequest.ip→ firstx-forwarded-for→x-real-ip→"unknown". Unknown-IP requests are still rate-limited (bucketed as"unknown") rather than silently shared.app.ts: passtrustProxy: 1(number of hops) instead of booleantrue. We sit behind exactly one reverse proxy in production; the number-based code path was explicitly hardened in 5.8.5.Public
/api/configstill exposestrustProxyas boolean — external contract unchanged.Unblocks PR #1215 (beta → main promotion) E2E Gates.
Test plan
npm run typecheckpassesconfig.test.ts68/68 passQuality GatespassesE2E Gateson PR release: promote beta to main #1215 passes after this lands on beta