Choose your stack

Stacks without a card

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

  1. OWASP Top 10:2025 A06 Insecure Design
  2. OWASP API Security Top 10 2023: API4 Unrestricted Resource Consumption
  3. CWE-770: Allocation of Resources Without Limits or Throttling
  4. CWE-400: Uncontrolled Resource Consumption
  5. OWASP Denial of Service Cheat Sheet

Guides on this weakness

Guide

Design a safer file-upload pipeline

Treat upload receipt, content processing, storage, and later delivery as separate security decisions.

Guide

Bound API work, not just request counts

Protect availability and operating cost with limits on input, per-request work, concurrency, queues, and downstream spending.

Guide

Extract archives without escaping the destination

Prevent traversal, link tricks, overwrites and decompression exhaustion while preserving legitimate file extraction.

Guide

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.

Guide

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.

Guide

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.

Guide

Bound background jobs and make retries safe

Keep queues, workers and paid dependencies within a defined budget when clients retry, cancel or disappear.

Guide

Bound agent spending, memory and recovery

Enforce budgets and stop conditions outside the model, and make retained context and side effects recoverable.

Guide

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.

Guide

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

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.

Guide

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.

Reference

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.

Guide

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.

Recipe

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.

Guide

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.