All vulnerabilities
MediumA05:2021CWE-307Security Misconfiguration

Missing Rate Limiting

Without rate limiting, attackers can brute-force passwords and OTPs, scrape your entire database, enumerate valid accounts, and spam your API with unlimited requests at zero cost.

What Is Missing Rate Limiting?

Rate limiting controls how many requests a client can make in a given time period. Without it, attackers can automate attacks that depend on volume — brute-forcing passwords, enumerating valid accounts, scraping all your data, or overwhelming your AI endpoints and running up your API bill.

How It Works

Password brute force:

# Without rate limiting, an attacker can try thousands of passwords per second
for password in $(cat rockyou.txt); do
  curl -s -X POST https://yourapp.com/api/login \
    -d "{\"email\":\"admin@yourapp.com\",\"password\":\"$password\"}"
done

A 6-character password with lowercase letters has ~300 million combinations — crackable in minutes without rate limiting.

OTP/2FA bypass:

# 6-digit OTP has 1,000,000 combinations
# Without rate limiting, crackable in ~16 minutes at 1000 req/sec

Account enumeration:

# Scrape all user emails via sequential ID access
for id in $(seq 1 100000); do
  curl https://yourapp.com/api/users/$id | jq .email
done

AI endpoint abuse:

Each request to your LLM-powered endpoint costs money. Without rate limiting, competitors or attackers can drain your OpenAI budget overnight.

Real-World Impact

  • Account takeover — brute-forced credentials or OTPs
  • Data scraping — extract your entire user base or product catalog
  • Financial damage — AI/LLM API costs explode from unbounded usage
  • DoS — legitimate users can't reach the service during an attack
  • Competitive intelligence — enumerate pricing, products, or users

How to Fix

nginx rate limiting (infrastructure level):

# Limit API to 10 requests/second with burst of 20
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
 
location /api/login {
    limit_req zone=login burst=3 nodelay;
    proxy_pass http://backend;
}
 
location /api/ {
    limit_req zone=api burst=20 nodelay;
    proxy_pass http://backend;
}

Application-level rate limiting (FastAPI + Redis):

from fastapi_limiter import FastAPILimiter
from fastapi_limiter.depends import RateLimiter
import redis.asyncio as aioredis
 
@app.on_event("startup")
async def startup():
    redis = await aioredis.from_url("redis://localhost")
    await FastAPILimiter.init(redis)
 
@app.post("/login")
@limiter.limit("5/minute")
async def login(request: Request, body: LoginRequest):
    ...

Add exponential backoff on failed attempts:

MAX_ATTEMPTS = 5
LOCKOUT_DURATION = 900  # 15 minutes
 
async def check_lockout(email: str):
    attempts = await redis.get(f"login_attempts:{email}")
    if attempts and int(attempts) >= MAX_ATTEMPTS:
        raise HTTPException(429, "Too many attempts. Try again in 15 minutes.")

What VibeWShield Detects

VibeWShield sends rapid repeated requests to authentication endpoints and checks whether the application responds with 429 status codes or any form of throttling. It also tests AI/LLM endpoints for rate limiting in safe-mode (non-authentication paths).

#rate-limiting#brute-force#api#authentication

Free security scan

Test your app for Missing Rate Limiting

VibeWShield automatically checks for Missing Rate Limiting and 40+ other vulnerabilities using 63 scanners — in under 3 minutes, no signup required.

Scan your app free