Rate limiting implemented
Why it matters
Absent rate limiting on authentication endpoints is one of the most commonly exploited API weaknesses — OWASP API 2023 lists it under both API4 (unrestricted resource consumption) and API7 (authentication failures). Without it, an attacker can mount unlimited credential stuffing or brute-force attacks against your login, signup, and password-reset routes at no cost. CWE-770 and CWE-307 (improper restriction of excessive authentication attempts) both apply. In serverless environments, an in-memory rate limit resets on every cold start and is effectively no limit at all.
Severity rationale
Critical because unlimited authentication attempts enable automated credential stuffing and brute-force attacks that compromise user accounts with no server-side barrier.
Remediation
Add rate limiting in src/middleware.ts starting with authentication endpoints. For Next.js on Vercel, use @upstash/ratelimit with a Redis-backed sliding window — it works in Edge Middleware and survives cold starts:
import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis'
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, '15 m'), // 10 attempts per IP per 15 min
})
const { success } = await ratelimit.limit(ip)
if (!success) return new Response(null, { status: 429 })
Apply stricter limits to authentication routes (10/15min), looser limits to general API routes (100/min). Never use an in-memory counter in serverless — it resets on cold start and provides no protection.
Detection
- ID:
rate-limiting - Severity:
critical - What to look for: Enumerate all API routes and check for rate limiting on each. Look for: rate limiting middleware (upstash/ratelimit, express-rate-limit, rate-limiter-flexible, slow-down); platform-level rate limiting config (Vercel Edge Middleware with rate limiting, Cloudflare rate limiting rules, API Gateway throttling); manual rate limiting implementation using Redis or a key-value store. Pay particular attention to high-risk endpoints: authentication (login, signup, password reset), payment operations, email-sending endpoints, and any endpoint that is expensive to compute or that exposes sensitive data. Implementation correctness matters: If rate limiting uses a database count query followed by a conditional insert (check-then-act pattern), flag this as a race condition vulnerability — concurrent requests can bypass the limit. Atomic operations are required for correctness: Redis INCR, PostgreSQL advisory locks, database upsert with conflict handling, or a dedicated rate limit library (e.g., @upstash/ratelimit, rate-limiter-flexible). A check-then-act implementation is a FAIL even if the intent is correct.
- Pass criteria: Rate limiting is implemented with no more than 100 requests per minute per IP on at least authentication endpoints, expensive operations, and any public-facing API endpoints. The implementation is tied to a persistent store (Redis, Upstash, etc.), not in-memory (which resets on cold start). Limits are reasonable (e.g., not 10,000 req/min per IP).
- Fail criteria: No rate limiting of any kind found on any API route. Do not pass when rate limiting exists only in-memory (no persistent store) — this is ineffective in serverless environments. Or authentication endpoints have no rate limiting.
- Skip (N/A) when: The project has no API routes accessible without prior authentication AND sits behind an API gateway or proxy that enforces rate limiting. Signal: all routes require auth AND vercel.json or other config shows edge-level rate limiting enforced upstream. (This is rare — default behavior is to fail if no evidence of rate limiting.)
- Detail on fail: Example:
No rate limiting on POST /api/auth/login. Identify which high-risk endpoints lack rate limiting (e.g., "No rate limiting found on POST /api/auth/login, POST /api/auth/register, or POST /api/contact; no rate limit middleware in dependencies"). Max 500 chars. - Remediation: Add rate limiting in
src/middleware.tsor route handlers to your API immediately, starting with authentication endpoints. For Next.js on Vercel, the easiest approach is Upstash Rate Limit with their@upstash/ratelimitpackage and a Redis database: it works in Edge Middleware and Serverless Functions. Implement a sliding window or fixed window limit (e.g., 10 login attempts per IP per 15 minutes). For self-hosted Express/Fastify, useexpress-rate-limitwith a Redis store. Apply rate limiting in middleware rather than per-route to avoid forgetting routes. Log rate limit hits so you can tune the limits. - Cross-reference: For a deeper analysis of authentication security, the SaaS Auth & Sessions Audit covers session management and auth flow security in detail.
External references
- cwe · CWE-770 — Allocation of Resources Without Limits or Throttling
- cwe · CWE-307 — Improper Restriction of Excessive Authentication Attempts
- owasp:2021 · A04 — Insecure Design
- owasp:2021 · A07 — Identification and Authentication Failures
Taxons
History
- 2026-04-18·v1.0.0·Initial import from saas-api-design·automated