Skip to content

fix(security): prevent rate limit bypass via X-Forwarded-For spoofing#338

Merged
Priyanshu-byte-coder merged 1 commit into
Priyanshu-byte-coder:mainfrom
anshul23102:fix/public-profile-rate-limit-spoofing
May 19, 2026
Merged

fix(security): prevent rate limit bypass via X-Forwarded-For spoofing#338
Priyanshu-byte-coder merged 1 commit into
Priyanshu-byte-coder:mainfrom
anshul23102:fix/public-profile-rate-limit-spoofing

Conversation

@anshul23102
Copy link
Copy Markdown
Contributor

Closes #337

What was wrong

getRateLimitKey() in src/app/api/public/[username]/route.ts used x-forwarded-for as the primary source for the rate limit key. This header is a plain HTTP request header — any caller can set it to an arbitrary value on every request. This made the 30 req/min in-memory rate limiter completely ineffective against anyone who rotated the header, allowing unbounded requests to the public profile endpoint and full exhaustion of the shared GITHUB_TOKEN quota (5,000 req/hr).

What changed

  • Removed x-forwarded-for from the rate limit key lookup chain
  • req.ip is now the primary key — the Next.js/Vercel runtime populates this from the verified network-layer source address, which cannot be set by the caller
  • x-real-ip is kept as a fallback for non-Vercel self-hosted deployments
  • Added an explanatory comment in the function so the intentional exclusion of x-forwarded-for is clear to future contributors

Files changed

  • src/app/api/public/[username]/route.tsgetRateLimitKey() function only

Testing

The fix can be verified locally by running the endpoint with a custom X-Forwarded-For header after more than 30 requests — the 429 response should now trigger based on the actual connection IP regardless of the header value.

Type of change

  • Bug fix
  • Security improvement

The public profile endpoint used x-forwarded-for as the primary key for
IP-based rate limiting. This header is fully client-controlled: an attacker
can set it to a different value on every request, making the 30 req/min
limit completely ineffective.

Switch to req.ip as the primary key. The Next.js/Vercel runtime derives
req.ip from the verified network-layer source address and it cannot be
set by the caller. Fall back to x-real-ip only when req.ip is unavailable.

This prevents unauthenticated callers from exhausting the shared
GITHUB_TOKEN quota (5 000 req/hr) and degrading service for all users.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 19, 2026

@anshul23102 is attempting to deploy a commit to the PRIYANSHU DOSHI's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your first PR on DevTrack! 🎉

A maintainer will review it within 48 hours. While you wait:

  • Make sure CI is passing (type-check + lint)
  • Double-check the PR description is filled out and the issue is linked
  • Feel free to ask questions in Discussions if you need help

Copy link
Copy Markdown
Owner

@Priyanshu-byte-coder Priyanshu-byte-coder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. x-forwarded-for is a plain request header — any caller can set it arbitrarily per request, completely bypassing the rate limit. req.ip is populated by the Vercel/Next.js runtime from the verified network-layer source address and cannot be spoofed. Clean one-liner fix.

@Priyanshu-byte-coder Priyanshu-byte-coder added gssoc:approved GSSoC: PR approved for scoring level:intermediate GSSoC: Intermediate difficulty (35 pts) gssoc26 GSSoC 2026 contribution type:security GSSoC type bonus: security (+20 pts) type:bug GSSoC type bonus: bug fix quality:clean GSSoC: Clean quality multiplier (×1.2) labels May 19, 2026
@Priyanshu-byte-coder Priyanshu-byte-coder marked this pull request as ready for review May 19, 2026 05:13
@Priyanshu-byte-coder Priyanshu-byte-coder merged commit 4a073d0 into Priyanshu-byte-coder:main May 19, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc:approved GSSoC: PR approved for scoring gssoc26 GSSoC 2026 contribution level:intermediate GSSoC: Intermediate difficulty (35 pts) quality:clean GSSoC: Clean quality multiplier (×1.2) type:bug GSSoC type bonus: bug fix type:security GSSoC type bonus: security (+20 pts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Public profile rate limiter bypassed via X-Forwarded-For header spoofing

2 participants