Skip to content
Files and resources Reviewed 2026-09-12

Uncontrolled resource consumption

An operation can be valid yet consume an unreasonable amount of CPU, memory, disk, connections, or paid service capacity. Repeatedly invoking it can deny service to other users. Examples include unbounded batch requests, oversized bodies, pathological regular expressions, decompression, and expensive report generation.

Trust boundary: a request may ask for work, but the service must decide how much work it can perform. Apply limits before allocation or scheduling; a timeout after a large allocation does not recover the memory already consumed.

Unsafe example: accept any batch size

function recordIds(body) {
  return body.ids;
}
// Scheduling all returned IDs concurrently can exhaust downstream capacity.

Safer example: define a bounded request contract

This JavaScript helper expects already-parsed JSON. It caps a batch at 20 positive integer IDs and rejects duplicates, preventing callers from multiplying the same work within one batch.

function recordIds(body) {
  if (body === null || typeof body !== 'object' || Array.isArray(body)
      || !Array.isArray(body.ids) || body.ids.length < 1
      || body.ids.length > 20) {
    throw new TypeError('Expected 1 to 20 record IDs');
  }
  if (body.ids.some(id => !Number.isSafeInteger(id) || id <= 0)) {
    throw new TypeError('Invalid record ID');
  }
  const ids = new Set(body.ids);
  if (ids.size !== body.ids.length) {
    throw new TypeError('Duplicate record ID');
  }
  return [...ids];
}

For an Express application, configure body limits before parsing; for example, express.json({limit: '16kb', inflate: false}) deliberately rejects compressed JSON bodies and caps this small API's payload. Return a controlled client error when validation fails. The Express API reference documents parser options; choose limits for the actual feature rather than copying a number to every route.

The function only bounds one batch. Enforce per-user and per-tenant request and work quotas, bounded worker queues, concurrency limits, and database statement deadlines. Authorize every selected record. A million concurrent batches remain expensive even if each has 20 IDs. An IP-only limit may penalize shared networks and can be insufficient against distributed clients.

Set connection and request deadlines at the proxy and runtime, and propagate cancellation into downstream work. A client disconnect or a rejected Promise.race does not automatically stop a database query or background task. Node's HTTP documentation distinguishes request and socket timeout settings; verify their behavior for the runtime and proxy in use.

For expensive asynchronous jobs, admit work only when capacity exists, use idempotency where the operation supports it, and expire abandoned work. Watch queue length and saturation, not only HTTP status. Autoscaling may preserve availability while creating an unacceptable cost increase.

Regression test

Locally accept batches of 1 and 20 IDs; reject 0, 21, duplicates, fractions, strings, and numbers outside the safe integer range. Check a body just above the parser limit returns an expected error before invoking downstream work. With a small fake worker pool, assert the configured concurrency cap and cancellation behavior. Use bounded fixtures, not production load or a large denial-of-service payload.

Related: archive extraction, regular expression injection, integer overflow, and object authorization.

References: CWE-400 — uncontrolled resource consumption and CWE-770 — allocation of resources without limits or throttling.