Skip to content

VNX-400: Uncontrolled Resource Consumption from a request-supplied size

A number read from the HTTP request (Flask, Django, DRF, or an unbounded FastAPI int/float route parameter) sets a Python loop count, sleep, allocation, repetition or exponent with no upper bound, so one request can exhaust CPU, memory or a worker.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-400
Severity Medium
SARIF level warning
Kind sast
Languages Python
CWE CWE-400
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C
Tags resource-consumption cwe-400
Source internal/sast/rules/vnx-400.rego

Overview

VNX-400 maps to CWE-400: Uncontrolled Resource Consumption. CWE-400 is broad; this rule reports its most concrete line-level form in Python: a Flask, Django or DRF request value (request.args, form, values, json, GET, POST, data, query_params, headers, cookies), used directly or through a variable assigned from it in the 10 lines above, as

  • the count of range(...),
  • the duration of time.sleep(...),
  • the size of bytearray(), bytes(), os.urandom(), secrets.token_bytes()/token_hex()/token_urlsafe(), numpy zeros/ones/empty/full/arange, .read() or .recv(),
  • the width of str.zfill(), ljust(), rjust() or center(),
  • the multiplier of a string or list repetition ("=" * n, [x] * n),
  • the exponent of **,

with no upper bound in between.

Not reported: a value bounded first (min(...), an if comparison of the variable, a max/min clamp reassignment), constants, environment and settings values, len() of the input, test files, comments and strings. A limit enforced in another function or by a schema validator is not seen, and unbounded work driven by other sources is out of scope.

Why This Matters

?count=1000000000 turns one request into a billion iterations, a gigabyte allocation or a worker asleep for a day. A handful of such requests takes the service down without any authentication.

What Gets Flagged

n = request.args.get("count", type=int)
return jsonify([make_code() for _ in range(n)])       # FLAGGED

delay = float(request.GET.get("delay", "0"))
time.sleep(delay)                                      # FLAGGED

exp = int(request.form["exp"])
return str(10 ** exp)                                  # FLAGGED

Not flagged:

n = min(request.args.get("count", 10, type=int), MAX_COUNT)
return jsonify([make_code() for _ in range(n)])

Remediation

  1. Clamp request-supplied sizes to a fixed maximum (min(value, LIMIT)) or reject values above it with 400.
  2. Enforce request body and upload size limits in the framework (MAX_CONTENT_LENGTH, DATA_UPLOAD_MAX_MEMORY_SIZE).

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-400
// nosec vnx-400

Or record an ignore rule: vulnetix ignore add --rule vnx-400 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-400.rego, cli/internal/sast/docs/vnx-400.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.