Skip to content

fix: prevent IP spoofing in rate limiter via trusted proxy validation#867

Merged
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
DeePrincipal-dev-lang:fix/ratelimit-trusted-proxy-ip-spoofing
Jun 30, 2026
Merged

fix: prevent IP spoofing in rate limiter via trusted proxy validation#867
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
DeePrincipal-dev-lang:fix/ratelimit-trusted-proxy-ip-spoofing

Conversation

@DeePrincipal-dev-lang

Copy link
Copy Markdown
Contributor

fix: prevent IP spoofing in rate limiter via trusted proxy validation

Summary

getClientIP() in src/lib/ratelimit.ts unconditionally trusted the x-forwarded-for header,
allowing any client to rotate fake IP addresses in each request and bypass per-IP rate limits
entirely. This fix introduces trusted proxy validation so proxy headers are only honoured when
the connection genuinely originates from a known proxy.

Changes

src/lib/ratelimit.ts

  • Added parseTrustedProxyIPs(envValue) — parses the TRUSTED_PROXY_IPS env var into a
    Set of trusted proxy IPs
  • Added getTrustedProxyIPs() — reads process.env.TRUSTED_PROXY_IPS at call time
  • Updated getClientIP() with three distinct paths:
    • Trusted proxy — connection IP matches TRUSTED_PROXY_IPS → x-forwarded-for / x-real-ip are
      trusted; leftmost IP returned
    • Untrusted connection (proxy IPs configured but source not in list) → all proxy headers
      ignored; falls back to 127.0.0.1, collapsing all spoofed header values into one rate-limit
      bucket
    • No proxy config — legacy behaviour preserved for unconfigured deployments

.env.example

  • Added TRUSTED_PROXY_IPS with full documentation, format examples, and a security warning
    about leaving it unset

src/lib/ratelimit.test.ts (new)

  • 25 tests across 5 suites: parseTrustedProxyIPs, trusted proxy extraction, spoofing
    prevention, legacy (no config), and sliding window rate limit behaviour

How to configure

Single proxy (e.g. nginx)

TRUSTED_PROXY_IPS=10.0.0.1

Multiple proxies / load balancers

TRUSTED_PROXY_IPS=10.0.0.1,10.0.0.2,172.16.0.1

Leave unset only if the app is exposed directly to the internet with no proxy in front of it.

Testing

npm test -- --run src/lib/ratelimit.test.ts

25 passed

Acceptance Criteria

  • A request with a spoofed x-forwarded-for from an untrusted source is rate-limited by
    actual connection IP
  • Trusted proxy configurations correctly extract the real client IP
  • All rate-limit tests pass with the updated extraction logic

Closes #722

- Add parseTrustedProxyIPs() and getTrustedProxyIPs() helpers to read
  TRUSTED_PROXY_IPS env var as a Set of trusted proxy IP addresses
- Update getClientIP() to only trust x-forwarded-for / x-real-ip headers
  when the direct connection IP matches a configured trusted proxy
- Untrusted connections fall back to 127.0.0.1, collapsing all spoofed
  header values into one rate-limit bucket
- Add TRUSTED_PROXY_IPS documentation to .env.example
- Add ratelimit.test.ts with 25 tests covering trusted proxy, spoofing
  prevention, legacy (no config), and sliding window behaviour
@drips-wave

drips-wave Bot commented Jun 30, 2026

Copy link
Copy Markdown

@DeePrincipal-dev-lang Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@RUKAYAT-CODER

Copy link
Copy Markdown
Contributor

Thank you for contributing to the project.

@RUKAYAT-CODER
RUKAYAT-CODER merged commit c9ddace into rinafcode:main Jun 30, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] Rate limiter trusts x-forwarded-for without proxy validation — IP spoofing possible

2 participants