Skip to content

fix: add rate limiting to /api/profile to prevent DoS amplification#196

Open
nishit546 wants to merge 1 commit into
SamXop123:mainfrom
nishit546:fix/rate-limiting-dos-protection
Open

fix: add rate limiting to /api/profile to prevent DoS amplification#196
nishit546 wants to merge 1 commit into
SamXop123:mainfrom
nishit546:fix/rate-limiting-dos-protection

Conversation

@nishit546

@nishit546 nishit546 commented Jun 16, 2026

Copy link
Copy Markdown

Description

Adds two-tier rate limiting to the /api/profile\ endpoint to prevent DoS amplification and resource exhaustion.

Problem

Each /api/profile\ request triggers up to 7 external API calls (GitHub REST × 4, GitHub GraphQL, GitHub CDN, LeetCode/Codeforces/CodeChef). There was zero rate limiting, allowing an attacker to:

  • Amplify external API consumption 7× per request using random usernames (bypasses cache)
  • Exhaust GitHub's 5,000/hr rate limit in under 15 minutes
  • Generate excessive Vercel edge function costs on free tier

Solution

  • Global rate limiter: 30 requests/minute per IP (covers all users)
  • Username-based cooldown: 5 requests/minute per username (prevents username cycling attacks)
  • Uses \express-rate-limit\ v7 with standard rate-limit headers

Changes

File Change
\src/server.js\ Added global (30/min/IP) and username-based (5/min) rate limiters applied to /api/profile\
\package.json\ Added \express-rate-limit@^7.5.0\ dependency

Closes

Closes #196

@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

@nishit546 is attempting to deploy a commit to the Dot_NotSam's projects Team on Vercel.

A member of the Team first needs to authorize it.

@SamXop123 SamXop123 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for the PR! A few updates needed:

  1. Enable Proxy Trust: Add app.set('trust proxy', 1); after const app = express(); so rate limiting doesn't block all users sharing the Vercel proxy.
  2. Update Thresholds: Change the window to 15 seconds (windowMs: 15 * 1000) and the request limit to 10 (max: 10).
  3. Return SVG instead of JSON: Returning JSON causes broken image placeholders. Use express-rate-limit's handler to return an SVG error instead:
handler: (req, res) => {
  res.setHeader('Content-Type', 'image/svg+xml');
  const svg = renderGracefulError({
    code: 'RATE_LIMIT',
    detail: 'Too many requests. Please try again in 15 seconds.',
  });
  res.status(429).send(svg);
}

Adds two-tier rate limiting with SVG error responses:
- trust proxy enabled for Vercel deployment
- Global limiter: 10 requests per 15s per IP
- Username-based limiter: 10 requests per 15s per username
- Returns rate-limited SVG (not JSON) so README image embeds
  render the error instead of showing a broken placeholder

Closes SamXop123#191
@nishit546 nishit546 force-pushed the fix/rate-limiting-dos-protection branch from f311bcd to 0ffb3dc Compare June 18, 2026 05:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants