Unrestricted Resource Consumption
A marketplace app lets a list endpoint take its page size straight from the request, with no server cap. An attacker asks for 250,000 records in one call, scraping the whole catalog and pinning the database, and you ship a server-side maximum page size.
What Is Unrestricted Resource Consumption?
Unrestricted Resource Consumption (OWASP API4:2023, previously framed as Lack of Resources & Rate Limiting in API4:2019) covers endpoints that place no bound on how much a single request can consume, or how often a client may call them. A classic shape is a list endpoint that takes its page size straight from the request and passes it to the database with no server-side maximum. The parameter is legitimate, the client uses it for normal pagination, but because nothing caps it, a caller can ask for the entire table in one request. This exercise puts you on both sides. As Bob, a data-hungry attacker holding an ordinary member account on Vendlo, a secondhand-marketplace app, you open the public browse feed, reload it with the network tools open to capture the GET /v1/listings call, and see that the page size is a caller-controlled limit parameter over a catalog of 240,118 listings. You rebuild the call in an API tester asking for 250,000 records in a single page, and the server obeys: one response carrying the entire catalog, 183 MB, with the database query pinned for nearly nine seconds. That one flaw does double duty, scraping the whole catalog and its pricing while acting as a cheap denial-of-service lever. As Alice, the backend engineer who owns the catalog API, you receive the monitoring alert, open the listings handler, and see the page size taken from the request and handed straight to the query with no upper bound. You ship the fix: clamp the requested page size to a server-side maximum so no single request can force the server past one bounded page, keep the cap on the server where the caller cannot raise it, and pair it with cursor pagination so large result sets stay reachable in bounded pages. A re-probe replays the same 250,000 request and returns a bounded page of 100 at 200 OK, proving the endpoint still works while the unbounded cost is gone. The exercise closes with quiz questions on why an uncapped page size is both a scrape and a denial-of-service risk, where the maximum belongs, and why a 200 with a smaller payload is the correct outcome rather than a 403.
What You'll Learn in Unrestricted Resource Consumption
- Recognize unrestricted resource consumption where an endpoint places no bound on how much a single request can consume, so one call can force unlimited work
- Understand that a caller-supplied page size (or count, size, or depth) with no server-side maximum lets a single request return an entire dataset at once
- See that an uncapped page size is both a mass-scraping vector and a denial-of-service lever, because one oversized request exhausts memory and pins a database connection
- Distinguish this from object-level access flaws, over-serialization of fields, and authentication gaps; here authentication is fine and the missing control is a resource bound per request
- Apply the fix: clamp the requested page size to a server-side maximum, keep the cap on the server, paginate large result sets with a cursor, and add rate limiting per client and time window
Unrestricted Resource Consumption — Training Steps
-
A public browse feed
Vendlo is a secondhand-marketplace app: members list things to sell, and anyone can browse the catalog. Today Bob is targeting Vendlo. He wants two things from it: the entire live catalog and its pricing, to resell to a competitor, and a cheap way to knock the API over if he decides to. He signed up as an ordinary member and opens the public browse feed to see how it loads.
-
Watch the request
The grid Bob is looking at was drawn from data the app fetched over the API. It shows 24 listings and a note that there are far more behind them. Bob opens the browser network tools and reloads the page once to capture the call the app makes to build the feed.
-
The page size is the caller's
The reload was captured, and the request is sitting in the Network panel. Bob reads how the app asked for its page of listings.
-
A quarter-million behind the page
Bob opens the response the endpoint returned and reads what it says about the size of the catalog.
-
Ask for everything
Bob rebuilds the same call in the API tester and changes one thing: instead of a page of 24, he asks for 250,000 listings in a single request. If the server honors it, one call will hand him the entire catalog.
-
One request, the whole catalog
The server did exactly what it was asked. The response tells the story of what that cost.
-
The storefront buckles
That one request is still running, grinding through a quarter-million rows and holding a database connection the whole time. Vendlo's connection pool is small, so while that query ties a connection up, the public storefront cannot get one of its own. Bob reloads Vendlo's page to see what a real shopper would see right now.
-
Real shoppers, locked out
The same endpoint that just handed Bob the whole catalog now cannot serve an ordinary shopper. The API tester still shows his 200 with the full catalog; the storefront beside it shows what everyone else gets.
-
Knowledge check
You just watched one request pull a quarter-million records and stall the database. Lock in why.
-
The alert lands
You own Vendlo's catalog API. Overnight, monitoring flagged a single request that returned the entire catalog and held a database connection open for nine seconds, with API latency spiking across every endpoint while it ran. Security operations has emailed you.