Inference Side Channels · 4 of 5L3offensive security
Denial and Resource Amplification: Sponge Inputs and Denial-of-Wallet
You do not need to crash a model to take it down — you can make each request so expensive that serving it, or paying for it, becomes the attack.
Abstract
Availability attacks on model serving do not require crashing anything. They exploit the fact that inference cost is input-dependent and, for generation, potentially unbounded. This article examines two families: sponge inputs, which maximize per-request compute or energy to degrade throughput for everyone, and denial-of-wallet, which drives up a victim's metered bill by inducing long or numerous generations. It explains why input-dependent cost is the root vulnerability, quantifies amplification as the ratio of induced cost to attacker effort, and pairs each attack with a bounding or metering defense. The key takeaway is that inference is a metered, input-dependent resource, so every cost dimension — tokens, compute, memory, wall-clock — must be explicitly bounded per request and per tenant, or an attacker will find the dimension you left unbounded.
Denial of service against a model rarely looks like a crash. It looks like everyone's requests getting slower, or a monthly bill arriving an order of magnitude too high. The reason is that inference is not a fixed-cost operation: the compute, memory, and time a request consumes depend on the input and, for generation, on how long the model decides to keep going. An attacker who understands this does not attack the model's correctness; they attack its economics. They craft inputs that cost the maximum to serve, or they induce generations that run as long as possible, turning the serving system's own resource consumption into the weapon. Shumailov and colleagues named the sharpest version of this a sponge — an input designed to soak up as much computation as possible.
Why input-dependent cost is the vulnerability
A serving system's capacity is finite: so many tokens per second, so much accelerator memory, so many concurrent requests. If every request cost the same, capacity planning would be simple and abuse would be limited to sending more requests, which rate limits handle. But inference cost is input-dependent. A longer prompt costs more to prefill; a request that triggers longer generation costs more to decode; certain inputs can push the model toward its worst-case compute or memory behavior. This variability is the vulnerability, because it lets a single request consume far more than its share.
Two levers make this potent. First, amplification: a small attacker effort (one crafted request) induces a large cost (maximal compute or a very long generation), so the attacker's cost-to-impact ratio is favorable. Second, meterability: many deployments bill per token or per compute-second, so induced cost is not just a throughput problem but a direct financial one — the attacker spends the victim's money. Both stem from the same root: cost is a function of the input, and the input is attacker-controlled.
The defensive principle is that every dimension of cost must be explicitly bounded. If tokens, generation length, compute per request, memory, and wall-clock are each capped per request and metered per tenant, then no single request can amplify beyond the cap and no tenant can spend beyond their budget. The attack surface is exactly the set of cost dimensions left unbounded.
- Explicitly bound every cost dimension — tokens, generation length, compute, memory, wall-clock — per request.
- Meter and cap cost per tenant so induced spend cannot exceed a budget.
- Treat any unbounded cost dimension as the attack surface an adversary will target.
Sponge inputs
Shumailov and colleagues introduced sponge examples: inputs crafted to maximize the energy and latency a neural network consumes to process them. The idea is to push the model toward its worst-case computational path — for sequence models, this often means inputs that defeat efficiency optimizations, keep more of the computation active, or maximize the work per token. The result is a request that looks ordinary in size but costs far more than a typical request to serve, degrading throughput for co-tenants and inflating energy cost.
Sponges are dangerous because they attack the average-case assumptions serving systems are tuned around. Capacity planning and batching assume requests cost roughly their typical amount; a sponge that costs many times the typical amount breaks that assumption and can starve other requests sharing the same hardware. And because the sponge is a single well-formed request, it slips past naive defenses that only count request volume.
The defense is to bound and meter actual resource consumption, not just request count. Enforce per-request compute and time budgets so a request that exceeds its allotment is throttled or terminated, and account real consumed cost per tenant rather than assuming uniform cost. Where worst-case paths are known, cap or normalize them so no input can reach the expensive corner of the model's behavior.
- Enforce per-request compute and wall-clock budgets, terminating requests that exceed their allotment.
- Meter real consumed resources per tenant rather than assuming uniform per-request cost.
- Cap or normalize known worst-case computational paths so inputs cannot reach them.
Denial-of-wallet and unbounded generation
Generation introduces a second, sharper cost lever: output length. Because an autoregressive model generates until it emits a stop condition or hits a limit, an attacker who can influence the model toward long outputs induces large decode cost per request. Combined with per-token billing, this becomes denial-of-wallet: the attacker does not degrade the service, they run up the victim's bill. Inducing a few very long generations, or many moderate ones, can multiply cost far beyond the attacker's own effort.
The influence can come from the prompt (asking, directly or indirectly, for exhaustive output), from a prompt injection that instructs the model to generate at length, or from inputs that make natural stopping unlikely. For agents, the risk compounds: an agent that loops, retries, or expands a task can generate enormous cost autonomously if an attacker nudges it into an expansive trajectory, and the bill accrues without any human noticing until it arrives.
The defense is hard limits and budgets. Cap maximum generation length per request, cap total tokens and cost per tenant per time window, and for agents cap loop iterations, tool calls, and total task budget. Alert on cost anomalies so a runaway is caught in minutes, not at billing time. These are not performance tunings but security controls: an unbounded cost is an open-ended liability.
- Cap maximum generation length per request and total tokens/cost per tenant per window.
- For agents, cap loop iterations, tool calls, and total task budget to bound autonomous cost.
- Alert on cost anomalies so a runaway is caught in minutes, not at billing time.
Quantifying amplification
The right metric for these attacks is amplification: the ratio of induced cost to attacker effort. A rate-limited request flood has an amplification near one — each attacker request costs the attacker as much as it costs the victim. A sponge or a denial-of-wallet attack has amplification much greater than one, because one cheap attacker action induces many units of victim cost. The higher the amplification, the more damage per unit of attacker resource and the more important tight bounds become.
This framing tells a defender where to spend. Bounding a dimension caps the amplification along it: a generation-length cap of L bounds decode amplification to L over the minimum, a per-request compute budget bounds sponge amplification, and a per-tenant cost cap bounds total wallet amplification regardless of per-request cleverness. The goal is to drive worst-case amplification down to a small, planned constant so that capacity and budget planning hold even under adversarial input.
The accounting below makes the target concrete: the victim's worst-case cost is the attacker's action count times the per-action amplification, so capping amplification and metering action count together bound the total. Neither alone suffices — unbounded amplification defeats rate limits, and unlimited actions defeat per-request caps — which is why per-request bounds and per-tenant metering must both be present.
- Cap amplification per dimension with generation-length, compute, and memory bounds.
- Meter attacker action count per tenant so total cost equals bounded amplification times bounded actions.
- Design for a small planned worst-case amplification so capacity and budget hold under adversarial input.
Deploying availability defenses
The controls compose into a layered availability posture. Per-request bounds (max input tokens, max output tokens, compute and wall-clock budgets, memory limits) cap what any single request can consume. Per-tenant metering and quotas (tokens, cost, and requests per window) cap what any tenant can consume in aggregate. Real-cost accounting (billing on actual consumed resources, not assumed uniform cost) ensures the meter reflects reality. And anomaly alerting catches runaways fast. Together these bound both amplification and volume, which is what the cost equation requires.
The synthesis is that inference availability is an economics problem: cost is input-dependent and potentially unbounded, so it must be explicitly bounded and metered along every dimension. Shumailov and colleagues' sponges show that even compute and energy are attackable, and denial-of-wallet shows that metered billing turns a throughput attack into a financial one. The rule is simple and unforgiving — bound every cost dimension per request, meter every tenant, and alert on anomalies — because an attacker will always probe for the one dimension you forgot to cap.
- Layer per-request bounds, per-tenant metering, real-cost accounting, and anomaly alerting.
- Audit for any unbounded cost dimension and cap it, since that is exactly where an attacker will push.
Key takeaways
- Availability attacks on serving exploit input-dependent, potentially unbounded inference cost rather than crashing anything.
- Sponge inputs are single well-formed requests crafted to maximize compute or energy, degrading throughput without tripping request-count limits.
- Denial-of-wallet induces long or numerous generations to run up a victim's metered bill, and agents can accrue this cost autonomously.
- The right metric is amplification — induced cost over attacker effort — which is much greater than one for sponge and wallet attacks.
- Bounding a cost dimension caps amplification along it, so generation-length, compute, memory, and per-tenant cost caps are security controls.
- Defense layers per-request bounds, per-tenant metering, real-cost accounting, and anomaly alerting; an attacker targets whatever dimension is left unbounded.
Practitioner Toolkit
Copy-paste, strictly defensive artifacts you can use today. Nothing here attacks a real system.
Run before exposing a serving endpoint to untrusted traffic.
- Max input tokens, max output tokens, compute, wall-clock, and memory are capped per request.
- Per-tenant token, cost, and request quotas are enforced per time window.
- Billing and quota use real consumed resources, not assumed uniform cost.
- Agent loops, tool calls, and total task budget are capped.
- Cost anomalies alert within minutes of a runaway.
- No cost dimension is left unbounded.
Sanitized skeleton to measure worst-case cost amplification on your own service (defensive).
# DEFENSIVE PROBE — what is our worst-case amplification?
function amplification_probe(service, benign_stress_inputs):
for x in benign_stress_inputs: # long prompts, long-output asks
cost = measure_real_cost(service.request(x)) # compute+tokens
amp = cost / baseline_cost
if amp > AMP_BUDGET:
flag("cost dimension unbounded", input=summarize(x), amp=amp)
# High amplification == a cost dimension to cap.Illustrative per-request and per-tenant cost policy.
cost_bounding_policy:
per_request:
max_input_tokens: bounded
max_output_tokens: bounded
compute_budget: bounded
wall_clock_budget: bounded
memory_limit: bounded
per_tenant:
tokens_per_window: quota
cost_per_window: quota
requests_per_window: quota
accounting:
bill_on_real_consumption: true
agents:
max_loop_iterations: bounded
max_tool_calls: bounded
total_task_budget: bounded
alerting:
cost_anomaly: minutesDo these first if you serve untrusted traffic.
- Cap max input and output tokens per request.
- Enforce per-tenant token and cost quotas per window.
- Bill and quota on real consumed resources.
- Alert on cost anomalies within minutes and cap agent loops and tool calls.
Glossary
- Sponge input
- An input crafted to maximize the compute or energy a model consumes to process it, degrading throughput.
- Denial-of-wallet
- An availability attack that inflates a victim's metered bill by inducing expensive generations rather than degrading service.
- Amplification
- The ratio of the cost induced on the victim to the effort spent by the attacker.
- Unbounded generation
- Allowing a model to generate without a strict length cap, letting an attacker induce very long, costly outputs.
- Prefill cost
- The compute to process a prompt before generation, which grows with prompt length.
- Decode cost
- The compute to generate output tokens, which grows with output length.
- Real-cost accounting
- Billing and quota based on actually consumed resources rather than an assumed uniform per-request cost.
- Per-tenant quota
- A cap on the tokens, cost, or requests a tenant may consume in a time window, bounding aggregate abuse.
References
- Shumailov et al., Sponge Examples: Energy-Latency Attacks on Neural Networks (arXiv 2006.03463)
- Kwon et al., Efficient Memory Management for LLM Serving with PagedAttention (arXiv 2309.06180)
- Leviathan et al., Fast Inference from Transformers via Speculative Decoding (arXiv 2211.17192)
- Kocher, Timing Attacks on Implementations of Diffie-Hellman, RSA, DSS, and Other Systems (CRYPTO 1996)
- NIST AI 100-2 e2023, Adversarial Machine Learning: A Taxonomy and Terminology