ASVS 5.0 V15.2.2 requires defenses against loss of availability from functionality that takes a long time or uses a lot of resources, based on your documented decisions for handling it. It is Level 2. In practice that means timeouts, size limits, concurrency caps and rate limits on the expensive paths, plus a written note on which paths those are.
Why it matters
Every application has a few operations that cost far more than the average request: report exports, image processing, search with wildcards, file parsing, regex over user text. An attacker only needs to find one and call it in a loop. No exploit is required, just volume.
How to implement it
First, list the expensive operations and decide for each what the limit is. Then enforce it in code, not just at the load balancer.
import asyncio
from fastapi import FastAPI, HTTPException, UploadFile
app = FastAPI()
export_slots = asyncio.Semaphore(4) # at most 4 exports at once
MAX_UPLOAD = 5 * 1024 * 1024 # 5 MB
@app.post("/reports/export")
async def export(user_id: str):
if export_slots.locked():
raise HTTPException(status_code=429, detail="Try again shortly")
async with export_slots:
try:
return await asyncio.wait_for(build_report(user_id), timeout=20)
except asyncio.TimeoutError:
raise HTTPException(status_code=503, detail="Report took too long")
@app.post("/import")
async def import_file(file: UploadFile):
data = await file.read(MAX_UPLOAD + 1)
if len(data) > MAX_UPLOAD:
raise HTTPException(status_code=413, detail="File too large")
return parse(data)
Add a per user rate limit on top, and move truly heavy work to a queue so the web tier stays responsive.
How to test it
Pick each documented expensive endpoint and send ten times the expected concurrency using a load tool. Confirm that excess requests get a 429 or 503 quickly, that unrelated endpoints stay fast, and that memory and CPU return to normal afterward. Also send an oversized body and a deliberately slow input and verify the size and time limits trigger.
Common mistakes
- A timeout on the client but none on the server, so the work continues after the caller leaves.
- Limits that apply per request but not in total, so many parallel requests still exhaust memory.
- Regular expressions with nested quantifiers run against user input.
- Treating the documented strategy as optional. The requirement is tied to what you wrote down.
Quick check
Is a CDN or WAF rate limit enough?
It helps, but it cannot see which calls are expensive in your code. Keep limits inside the application for the heavy paths.