mediumInfrastructure

No Rate Limiting on API Endpoints

What Is This Vulnerability?

API endpoints without rate limiting allow unlimited requests from any client. This enables brute-force attacks on login forms, credential stuffing, API abuse, data scraping at scale, and denial-of-service conditions. Without throttling, a single attacker can overwhelm your backend or exhaust expensive third-party API quotas.

Why It Happens

Rate limiting is often treated as an optimization rather than a security requirement. Early-stage applications focus on functionality and skip throttling. Developers may rely on their cloud provider's DDoS protection without realizing it does not cover application-layer abuse. Microservice architectures make it unclear which service should enforce limits.

Example Code

Vulnerableserver.ts
import express from "express";

const app = express();

app.post("/api/login", async (req, res) => {
  const { email, password } = req.body;
  const user = await authenticate(email, password);
  if (user) {
    res.json({ token: generateToken(user) });
  } else {
    res.status(401).json({ error: "Invalid credentials" });
  }
});
Fixedserver.ts
import express from "express";
import rateLimit from "express-rate-limit";

const app = express();

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 10,
  message: { error: "Too many login attempts, please try again later" },
  standardHeaders: true,
  legacyHeaders: false,
});

app.post("/api/login", loginLimiter, async (req, res) => {
  const { email, password } = req.body;
  const user = await authenticate(email, password);
  if (user) {
    res.json({ token: generateToken(user) });
  } else {
    res.status(401).json({ error: "Invalid credentials" });
  }
});

How Hackers Exploit It

Without rate limiting, attackers can launch automated credential stuffing attacks using lists of stolen passwords, trying thousands of combinations per minute. They can scrape entire databases through paginated API endpoints, exhaust paid third-party API quotas to cause financial damage, or simply flood endpoints to cause a denial of service.

How to Fix It

Implement rate limiting at multiple layers. Use a reverse proxy (nginx, Cloudflare) for global limits. Add application-level rate limiting with libraries like express-rate-limit or similar for your framework. Apply stricter limits on sensitive endpoints like login, registration, and password reset. Use sliding window algorithms and consider per-user, per-IP, and per-API-key limits.

Frequently Asked Questions

What endpoints need rate limiting the most?
Authentication endpoints (login, registration, password reset) need the strictest limits because they are prime targets for brute-force attacks. Other sensitive endpoints include payment processing, email sending, file uploads, and any endpoint that triggers expensive operations or accesses third-party APIs.
Should I rate limit by IP or by user?
Use both. IP-based limiting prevents anonymous abuse, while user-based limiting prevents authenticated users from abusing the API. Be aware that IP-based limiting can affect users behind shared NATs or corporate proxies. Combine with API key limits for machine-to-machine traffic.
What HTTP status code should rate limiting return?
Return HTTP 429 (Too Many Requests) with a Retry-After header indicating when the client can retry. Include the RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers so clients can proactively throttle themselves before hitting the limit.

Related Security Topics

Check Your Code for This Vulnerability

Run a free scan to check if your site is affected by no rate limiting on api endpoints.