1. What Is It?
Unrestricted Resource Consumption occurs when an API allows clients to trigger expensive operations without enforcing safe limits on request cost.
This is not only about high traffic. A single request can be enough to consume excessive CPU, memory, or backend capacity if the server blindly trusts attacker-controlled input.
In the previous guide, we covered Broken Object Property Level Authorization and how field-level access issues can expose or modify sensitive data. This guide focuses on what happens when the client controls how much work the API performs.
Read the API3 Guide2. Why It Matters
Unrestricted Resource Consumption is dangerous because:
- It can trigger denial-of-service conditions.
- CPU and memory usage can spike from a small number of requests.
- Backend systems can degrade for all users.
- Infrastructure costs can increase sharply.
- Stress conditions may expose internal diagnostics or secrets.
In real-world systems, this can lead to:
- Service instability and failed requests.
- Expensive database or cache expansion.
- Abuse of public endpoints without authentication.
- Unexpected disclosure under error or stress conditions.
Why OWASP classifies it as API4
APIs often expose powerful operations such as search, filtering, export, expansion, or generation without controlling how expensive those operations can become. OWASP highlights this category because a client-controlled request can turn availability issues into direct security impact.
3. How It Happens (Technical)
This issue appears when client-controlled input directly determines how much work the backend performs.
Common examples include pagination limits, recursive expansions, bulk exports, large uploads, or expensive pattern generation.
Common technical causes:
- No upper bound on search or pagination parameters
- No timeout or execution guard for expensive operations
- No cost budgeting for response generation
- Public endpoints treated as low risk
- Stress paths that expose internal debug information
Core Issue
api/search.py# vulnerable
def search(term, limit):
if limit < 1:
raise HTTPException(status_code=400, detail="limit must be positive")
expansion = [f"{term}-{i}-{term[::-1]}" for i in range(limit)]
return {
"count": len(expansion),
"results_preview": expansion[:5],
}Correct Direction
api/search.py# safer
MAX_LIMIT = 100
def search(term, limit):
if limit < 1:
raise HTTPException(status_code=400, detail="limit must be positive")
safe_limit = min(limit, MAX_LIMIT)
expansion = [f"{term}-{i}-{term[::-1]}" for i in range(safe_limit)]
return {
"count": len(expansion),
"results_preview": expansion[:5],
}Key concept: the client may request work, but the server must decide how much work is acceptable.
Attacker’s Perspective
From an attacker’s perspective, API4 is not only about sending many requests. It is about finding one parameter that makes each request much more expensive.
- Find parameters that control response size or processing depth
- Increase those values aggressively
- Probe for thresholds where behavior changes under stress
- Look for debug data or internal state exposed at high cost levels
If one crafted request consumes disproportionate resources, the API is already in dangerous territory.
4. Real-World Example
A common example is a search endpoint that accepts an unbounded limit value and performs expensive expansion directly from user input.
Example endpoint:
GET /api/search?term=a&limit=12000Expected behavior: search size should be capped and stress conditions should never expose internal diagnostics.
Vulnerable Logic
api/search.pyexpansion = [f"{term}-{i}-{term[::-1]}" for i in range(limit)]
data = {
"count": len(expansion),
"results_preview": expansion[:5],
}
if limit >= 10000:
data["stress_debug"] = {
"cache_state": "degraded",
"flag": FLAG,
}What is wrong: the API trusts an attacker-controlled limit value and performs synthetic expansion without any safe upper bound.
Result: the request becomes expensive enough to change system behavior and reveal internal debug data that should never appear in a normal response.
Common Variations
- Unbounded Search: large
limitor page values drive excessive response generation. - Recursive Expansion: nested or deep expansion paths create disproportionately expensive processing.
- Large Upload Abuse: file size or parsing cost is not constrained safely.
- Stress-Induced Disclosure: internal debug fields appear only when the system enters degraded states.
5. How To Prevent
1. Apply hard server-side limits
Search size, page size, expansion depth, upload size, and other cost-driving parameters must be capped by the server.
guards/request_cost.pyMAX_LIMIT = 100
safe_limit = min(limit, MAX_LIMIT)2. Use execution guards
Timeouts, concurrency limits, and worker controls help prevent one request from monopolizing backend resources.
3. Treat public endpoints as high risk
Public or unauthenticated endpoints should not be assumed safe. They often provide the easiest attack surface for cost abuse.
4. Never expose stress or debug data
Internal diagnostics should not appear in client responses, even when the system is overloaded or degraded.
5. Monitor for disproportionate cost patterns
Track request parameters, execution time, and abnormal thresholds so expensive paths are visible before they become outages.
Key Principle
- Limit cost at the server, not at the client
- Assume a single request can be expensive enough to matter
- Protect public endpoints with the same rigor as private ones
- Never let degraded states change what the API reveals
6. Detection Tips (Scanner Perspective)
Detecting API4 requires testing how the backend behaves as request cost increases, not only whether the endpoint responds successfully.
Common techniques:
- Increase limit and pagination values aggressively
- Measure response time, size, and behavioral changes
- Find thresholds where the API becomes unstable
- Check whether high-cost requests reveal debug fields or internal state
- Test public endpoints as well as authenticated ones
Key signal: if increasing a client-controlled parameter causes disproportionate backend work, unstable behavior, or stress-only disclosure, Unrestricted Resource Consumption is present.
7. Final Takeaway
Unrestricted Resource Consumption is not just a performance bug.
It exists whenever:
- The client can control request cost directly
- Server-side limits are missing or too weak
- Stress changes what the API returns
- Availability weakness turns into disclosure or instability
Every cost-sensitive endpoint should answer: Can a client force this API to do more work than the server safely allows?
If the answer is yes, the API is already exposed.