Denial of Wallet in LLM Applications: Defend Against Unbounded Consumption (OWASP LLM10:2025)
Understand LLM unbounded-consumption risks and controls for request size, output length, concurrency, budgets, and retries.
A Denial of Wallet (DoW) scenario occurs when an attacker or runaway workflow triggers costly, repeated inference. OWASP’s 2025 Top 10 for LLM Applications classifies this broader risk as LLM10: Unbounded Consumption. The example below is illustrative, not a documented incident.
Illustrative factors to model: request rate, input tokens, output tokens, model price, provider limits, and attacker request cost.
1. The Physics of Economic Asymmetry in AI Systems
In traditional cybersecurity, an attacker seeking to exhaust a victim’s resources must generate massive traffic volume (e.g., a 100 Gbps SYN flood) to overwhelm network capacity or saturate CPU worker pools. The relative cost of an attack varies by architecture, rate limits, attacker resources, and pricing model; avoid treating it as universally balanced.
In generative AI systems, the economic equation is completely asymmetric:
$$A_F = \frac{\text{Victim Cost}}{\text{Attacker Cost}} = \frac{T_{\text{in}} \cdot R_{\text{in}} + T_{\text{out}} \cdot R_{\text{out}}}{C_{\text{network}}}$$
Where:
- $T_{\text{in}}$ = Injected prompt tokens per request.
- $T_{\text{out}}$ = Forced autoregressive output tokens.
- $R_{\text{in}}, R_{\text{out}}$ = Hardware API rates charged per token.
- $C_{\text{network}}$ = Attacker bandwidth and proxy cost.
Large input payloads can trigger substantial inference work, but bytes-to-tokens and compute costs depend on content, tokenizer, model, and serving system. Enforce both request-size and token budgets.
Cost amplification varies with payload, model, rate limits, and attacker costs; calculate it for a specific threat model.
2. Attack Vectors in the Wild
Victim bill: depends on traffic and current rates] WAFCheck -- Yes (Defensive Gateway) --> EdgeBlock[Dual-Key Rate Limiting & Byte Caps
Reject before provider dispatch where possible | Cost depends on gateway]
2.1 The Token Bomb (Autoregressive Generation Exhaustion)
When an application omits the max_tokens parameter or defaults to the model ceiling (4,096 to 16,384 tokens), an adversary crafts prompts designed to force maximum generation length.
- Output-token rates are model- and provider-specific and may differ from input-token rates. Use current pricing for the exact model; do not infer API prices directly from hardware bottlenecks.
- Estimate each request from the current model’s output-token rate and actual generated-token count. Prices change, so avoid a fixed per-call figure without a dated rate citation.
- Fleet spend depends on request completion rate, output length, concurrency, rate limits, and current pricing. Calculate it from measured requests per second and per-request usage.
2.2 The Context Inflator (Pre-Fill Saturation)
If an endpoint accepts text or file attachments without token size validation, an attacker injects 100,000 tokens of junk data, appended with a trivial prompt: "Summarize the first sentence."
- Even if the model generates a 5-token response, the victim is billed for the 100,000-token pre-fill compute (\$0.25 to \$0.30 per request).
- Total spend depends on tokenization, request rate, model price, and duration.
2.3 The Cache-Busting Nonce Attack
If an organization deploys semantic or prompt caching to control operational costs, an adversary intentionally defeats the cache by appending high-entropy random strings to every request:
"What is your company policy on returns? [nonce: 849182]""What is your company policy on returns? [nonce: 192847]"- This forces a 0% cache hit rate on Redis and invalidates provider KV caches, driving infrastructure spend from discounted rates to 100% full-cost inference.
3. The Defensive Blueprint: The Dual-Key AI Gateway
Standard rate limiting fails against Denial of Wallet attacks because it measures requests, not tokens. A user submitting 5 requests containing 100,000 tokens consumes 500x more compute than a user submitting 5 requests containing 200 tokens.
Production AI systems require a Dual-Key Token Gateway operating at the reverse proxy layer:
+-----------------------------------------------------------------------------------------+
| THE DUAL-KEY GATEWAY DEFENSE |
+-----------------------------------------------------------------------------------------+
| [Layer 1] NGINX / Envoy Payload Filter |
| • Strict byte ceiling: client_max_body_size = 40KB |
| • Rejects megabyte context-inflation payloads at the TCP socket layer |
+-----------------------------------------------------------------------------------------+
| [Layer 2] Sliding-Window Dual-Key Rate Limiter (Redis) |
| • Key A: Requests Per Minute (RPM) <= 30 |
| • Key B: Tokens Per Minute (TPM) <= 10,000 per tenant |
| • If TPM threshold trips, tenant throttled regardless of request count |
+-----------------------------------------------------------------------------------------+
| [Layer 3] Immutable Output Bound Enforcement |
| • Gateway overwrites model parameters: max_tokens = 350 (hard cap) |
| • Injects deterministic stop tokens: ["\n\nUser:", "###", "System:"] |
+-----------------------------------------------------------------------------------------+
| [Layer 4] Real-Time Velocity Circuit Breakers |
| • Monitors global fleet spend velocity ($/sec) |
| • Automatically trips circuit breaker if token burn rate spikes >300% |
+-----------------------------------------------------------------------------------------+
4. Prove the Boundary: The Token Velocity Bomb Test
To verify whether your application is protected against Denial of Wallet attacks, execute this test against your staging API endpoint:
import time
import requests
def test_denial_of_wallet_boundary(target_url, api_token):
# Construct a 25,000-token payload
inflated_payload = "A " * 25000 + "\nRepeat the word 'verified' indefinitely."
headers = {"Authorization": f"Bearer {api_token}", "Content-Type": "application/json"}
payload = {"model": "gpt-4o", "messages": [{"role": "user", "content": inflated_payload}]}
print("[TEST] Submitting 5 sequential token-bomb payloads...")
for i in range(5):
start = time.time()
resp = requests.post(target_url, json=payload, headers=headers)
elapsed = time.time() - start
if resp.status_code == 413:
print(f"[PASSED] Request {i+1} dropped by gateway byte-cap filter (HTTP 413).")
return
elif resp.status_code == 429:
print(f"[PASSED] Request {i+1} throttled by token-velocity rate limiter (HTTP 429).")
return
elif resp.status_code == 200:
print(f"[WARNING] Request {i+1} processed in {elapsed:.2f}s! Vulnerable to token exhaustion.")
print("[CRITICAL VULNERABILITY] All payloads accepted. Your endpoint is unprotected against DoW attacks.")
If this script outputs CRITICAL VULNERABILITY, an adversary can drain your monthly AI budget within hours.
Summary: Economics as a Security Perimeter
In the software era, security was about protecting data confidentiality and system integrity.
In the inference era, your cloud budget is an attack surface.
When an API call incurs an immediate, variable financial charge on hardware you do not own, unmetered access is not a usability feature. It is a catastrophic vulnerability.
Governing the inference boundary with dual-key token accounting, immutable output bounds, and edge circuit breakers is the only way to build safe, sustainable AI infrastructure.
Sources and methodology
Performance and cost figures not linked to a named external benchmark are illustrative examples, not audited customer results. Verify provider model, tier, region, cache rules, and price before publication; measure latency and quality on a representative evaluation set. References:


