API Bugs

API Accepts Requests Without Rate Limiting

The POST /api/search endpoint accepts an unlimited number of requests per second from the same client. There is no per-client throttle and no 429 Too Many Requests response. A single client can saturate the server by sending requests in a tight loop without any backpressure.

MediumBeginnerAPI testingSecurity testingPerformance testing

// UNDERSTAND

// Symptoms

  • Sending 200 consecutive POST /api/search requests returns 200 on every call — no 429 is ever returned
  • Response time does not increase and no Retry-After header appears across the burst
  • Server CPU or database connection pool metrics spike sharply during the burst with no automatic throttle kicking in
  • No RateLimit-Remaining or X-RateLimit-* headers are present in any response

// Root Cause

  • No rate-limiting middleware (such as an nginx limit_req zone or an application-layer request counter) is applied to the endpoint — every request reaches the handler and triggers a full database query regardless of request frequency
  • The endpoint performs an expensive operation (full-text database search) on every call; without a per-client throttle, a single caller can exhaust the database connection pool and degrade performance for all users

// Where It Appears

  • Search endpoints that run full-text or complex database queries on every call
  • Publicly accessible API endpoints that are not behind an API gateway with built-in throttling
  • Endpoints that were rate-limited in the web layer (nginx) but are directly reachable on an internal port
  • Any API that processes computationally expensive requests without request-level throttling

// REPRODUCE & TEST

// How to Reproduce

  1. 01Obtain a valid bearer token by authenticating as a standard user
  2. 02Send POST /api/search with body { "query": "test" } and the bearer token; confirm the response is 200 OK
  3. 03Send the identical request 200 times in rapid succession with no delay between requests
  4. 04Inspect all response status codes — if every response is 200 and no 429 appears, the rate limit is absent

// Test Data Needed

  • A valid bearer token for a standard user account
  • A way to send many requests in rapid succession (Postman collection runner, curl loop, or a short script)

// Manual Testing Ideas

  • Use Postman's collection runner to send the search request 100 times with 0 ms delay and observe whether any 429 responses appear
  • Check response headers on each response for RateLimit-Remaining, X-RateLimit-Limit, or Retry-After — their absence indicates no rate limit is configured
  • Test both authenticated and unauthenticated request paths to confirm whether rate limiting differs for logged-in vs. anonymous users
  • Send the burst from two different IP addresses simultaneously and confirm whether a per-IP or per-account limit exists
  • Monitor server-side metrics (CPU, DB connections) during the burst to demonstrate the resource impact

// API Testing Ideas

  • Obtain a valid bearer token
  • Send POST /api/search with body { "query": "test" } once; assert the response is 200 and note any rate-limit headers
  • Send the same request 50 times with no delay
  • Assert that at least one response returns 429 Too Many Requests — if all 50 return 200, no rate limiting is in effect
  • If a 429 is received, assert the response includes a Retry-After header and confirm that waiting the specified duration before retrying returns 200 again

// Automation Idea

Send POST /api/search 50 times in a tight loop with no delay. Track the status code of each response. Assert that at least one response has HTTP status 429 Too Many Requests. If all responses are 200, fail the test and log the total request count alongside the absence of any rate-limit headers.

// Expected Result

After a configurable number of requests within a short window (e.g. 20 requests per 10 seconds), the endpoint returns 429 Too Many Requests with a Retry-After header.

// Actual Result (Example)

All 200 POST /api/search requests return 200 OK. No 429 is returned and no rate-limit headers appear in any response. The endpoint processes every request without throttling.

// REPORT IT

Example Bug Report

Title
POST /api/search accepts 200 consecutive requests with no rate limiting — no 429 returned
Severity
Medium
Environment
Staging environment Postman collection runner Authenticated as standard user Endpoint: POST /api/search
Steps to Reproduce
  1. 01Authenticate as a standard user and copy the bearer token
  2. 02Create a POST /api/search request with body { "query": "test" } and the Authorization header
  3. 03Run the request 200 times with no delay using Postman's collection runner
  4. 04Inspect the status code of each response
Expected Result
The endpoint returns 429 Too Many Requests after the per-client threshold is exceeded.
Actual Result
All 200 responses are 200 OK. No 429 is returned at any point. No rate-limit headers are present in any response.
Impact
A single client can saturate the search endpoint, causing high database load and degraded response times for all other users. Without throttling, the endpoint is also vulnerable to denial-of-service via automated traffic.

// RELATED