Choose your stack
Fix unbounded resource consumption in Node.js and Express
Bound every resource a request can consume: cap the body size as it is read (express.json's limit), cap the work one request asks for (a maximum item count), and rate-limit callers keyed on the connection address, not a header the client sets.
Open the fix card C# · ASP.NET CoreFix unbounded resource consumption in C# and ASP.NET Core
Bound every resource a request can consume: read the body with a byte cap (413 over it), cap the batch size (400 over it), and add the rate limiter (AddRateLimiter, a fixed window) keyed on the connection address, not a client header.
Open the fix card Python · FastAPIFix missing resource limits in Python and FastAPI
Bound every resource the client controls. Cap the request body while you read it -- count the stream and return 413 as soon as it exceeds the limit, never trusting Content-Length -- and bound pagination with Query(limit, ge=1, le=100) so an out-of-range page size is a 422.
Open the fix card Go · net/httpFix missing resource limits in Go and net/http
Cap the body with r.Body = http.MaxBytesReader(w, r.Body, limit): it counts bytes as they are read and stops at the limit whatever the client declares, so a chunked or lying request is bounded too.
Open the fix cardStacks without a card
- Python and Flask: no card yet. The nearest is Fix missing resource limits in Python and FastAPI, in the same language.
- Java and Spring Boot: no card yet. The nearest is Fix unbounded resource consumption in C# and ASP.NET Core.
- TypeScript and Next.js: no card yet. The nearest is Fix unbounded resource consumption in Node.js and Express, in the same language.
- Python and Django: no card yet. The nearest is Fix missing resource limits in Python and FastAPI, in the same language.
- Ruby on Rails: no card yet. The nearest is Fix unbounded resource consumption in Node.js and Express.
- PHP and Laravel: no card yet. The nearest is Fix unbounded resource consumption in Node.js and Express.
How it happens
- No limit bounds the request body, so a large or chunked payload is read fully into memory; raising a framework limit to silence a 413 removes even the default.
- The caller chooses the amount of work: a batch endpoint processes every item sent, or a page-size parameter returns the whole table, so a single request is arbitrarily expensive.
- There is no rate limit, so one client repeats an endpoint as fast as it can, exhausting CPU, a downstream dependency or the connection pool.
- A rate limiter is keyed on something the client controls -- an X-Client-Id header, an API key the client picks, or X-Forwarded-For without a trusted-proxy setup -- so rotating that value defeats it.
- The count is checked but not the per-item cost, so a few items that each trigger an expensive join or an unbounded regex do as much damage as a flood.
Fix principles
- Enumerate what one request can spend -- bytes read, items processed, rows returned, time, concurrency -- and set an explicit maximum for each.
- Cap the request body as it is read (the framework's body-size limit), so an over-size body is rejected with 413 before it is buffered; size the limit to the feature, do not raise it globally.
- Cap the work: reject a batch or page over N items with 400, and bound any caller-supplied count.
- Rate-limit by an identity the client cannot choose -- the connection's address, or an authenticated principal -- not a request header; return 429 with Retry-After. For several instances, use a shared counter and keep the per-instance cap as a floor.
- Give heavy or long work a timeout and backpressure so one caller cannot occupy every worker, and bound the per-item cost, not only the item count.
The scenario
A bulk quote API takes POST /quotes with an array of items and returns a quote per item. The fixed build caps the request body, caps the number of items, and rate-limits by the connection address; the vulnerable build sets none of these; the wrong build enforces the body and item caps but keys its rate limiter on a client-supplied header, so rotating the header lands in a fresh bucket each time.
How the cards prove it
- Run each card's tests in three modes: the fixed implementation must pass, and the vulnerable and the plausible-but-wrong implementations must fail. run-all.mjs does this for every card.
- The exploit tests send a body over the cap (expect 413), a batch over the item cap (expect 400), and a burst that rotates a client header (expect a 429 regardless, with Retry-After). The functional tests keep a small request, requests under the limit, and a body just under the cap working.
- On a running system, send an over-size body, an over-count batch, and a burst from one client that rotates its API-key or client-id header, and confirm the limits hold and the limiter keys on the connection or principal.
- Do not count on static analysis: no rule flags a missing body limit, a missing work cap, or a limiter keyed on a spoofable header. Each card's scannerRules records what was checked; the regression tests are the control.
Identifiers
CWE-770 (Allocation of Resources Without Limits or Throttling) is the weakness the cards show; CWE-400 (Uncontrolled Resource Consumption) is its parent. Neither is named in an OWASP Top 10:2025 category's official CWE list, so they are mapped here to A06 Insecure Design, which the category describes as covering missing resource limits and plausibility checks, consistent with the site's api-resource-limits guide. They map directly to API4:2023 Unrestricted Resource Consumption. CAPEC-130 (Excessive Allocation) and CAPEC-125 (Flooding) are attack patterns MITRE links to CWE-770. The 2025 CWE Top 25 ranks CWE-770 25th.
Attack patterns:
References
Guides on this weakness
Design a safer file-upload pipeline
Treat upload receipt, content processing, storage, and later delivery as separate security decisions.
Bound API work, not just request counts
Protect availability and operating cost with limits on input, per-request work, concurrency, queues, and downstream spending.
Extract archives without escaping the destination
Prevent traversal, link tricks, overwrites and decompression exhaustion while preserving legitimate file extraction.
Convert untrusted office documents and PDFs in an isolated parser
DOCX, XLSX and ODF files are ZIP archives of XML, and PDFs can carry scripts; the converters that read them are large C and C++ programs with a long CVE history. Check the package before any parser reads it, convert each document in a container with no network, no writable root and hard limits, kill it at a deadline, and re-render to pixels when people will open the result.
Secure WebRTC signaling, TURN relays and media servers
WebRTC encrypts media, but signaling decides whose keys you trust and TURN relays wherever it is allowed. Authorize every signaling message, mint short-lived TURN credentials, deny internal addresses and harden media servers.
Apply security limits to GraphQL, WebSocket and gRPC operations
Carry authorization and resource budgets past the initial HTTP request into resolvers, messages and long-lived streams.
Bound background jobs and make retries safe
Keep queues, workers and paid dependencies within a defined budget when clients retry, cancel or disappear.
Bound agent spending, memory and recovery
Enforce budgets and stop conditions outside the model, and make retained context and side effects recoverable.
Contain cascading failures and rogue agents
Stop a looping, compromised or drifting agent from spreading harm: kill switches, budget and rate limits, circuit breakers, behavior monitoring, blast-radius limits, quarantine, rollback and incident response, all enforced outside the agent.
Parse bounded JSON and XML into an explicit application schema
Separate parser capabilities from schema rules, reject ambiguous and coercible inputs, and implement the boundary in a complete Python project.
Case study: Log4Shell (CVE-2021-44228)
How a JNDI lookup in Apache Log4j became internet-wide remote code execution, why transitive and shaded dependencies made it so hard to patch, which mitigations held, and what it teaches about dependency inventory and SBOMs.
Keep HTTP services up under application-layer DDoS
Bound every phase of an HTTP request, patch for the HTTP/2 attack classes, rate limit at the edge and the origin, and shed load deliberately, with nginx, Envoy and Node.js settings tested against slow clients and bursts.
Threat pattern library for threat modeling
Thirty-two recurring threat patterns grouped by identity, authorization, parsers, concurrency, integrations, data exposure, supply chain, availability and AI agents, each with where it shows up on a data-flow diagram, mitigations, a verification step and STRIDE, CWE and CAPEC links, plus a YAML catalog and a script that lists patterns per diagram element.
Consume third-party APIs safely (OWASP API10:2023)
Treat every upstream and third-party API response as untrusted input: validate it against a schema, set connect and read timeouts, cap the response size, refuse to follow redirects blindly, keep TLS verification on, and scope the credentials you hold for each provider.
Call a hosted LLM API safely
A code-first checklist for wiring up an OpenAI or Anthropic API call from a backend: keep keys server-side, redact PII before prompts and logs, choose provider retention settings deliberately, validate structured output and still treat it as untrusted, and set timeouts, retries and per-user cost caps.
Sandbox model-generated code and computer-use agents
Run the code an agent writes, and agents that drive a browser or desktop, inside a boundary built for hostile code: a disposable runtime with no secrets and no default network, hard resource limits, and a person in front of every side effect.