VNX-606: Unchecked Input for Loop Condition
Reports a counted or count-down loop (C/C++, Java, Go) whose bound is a number parsed from argv, getenv, scanf, a request parameter or header, with no upper limit checked or clamped before the loop.
| Field | Value |
|---|---|
| Rule ID | VNX-606 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | C, C++, Go, Java |
| CWE | CWE-606 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L |
| Tags | loop-bound cwe-606 |
| Source | internal/sast/rules/vnx-606.rego |
Overview
VNX-606 maps to CWE-606: Unchecked Input for Loop Condition. It reports a loop for (...; i < N; ...), while (i < N) or Go for i := range N where N, within the 25 lines above, was:
- C/C++: assigned from
atoi/atol/strtol/strtoul/ntohl/ntohsoverargv,getenvoroptarg, or read withscanf("%u", &N). - Java: assigned from
Integer.parseInt/valueOf,Long.parseLongorScanner.nextIntoverrequest.getParameter/getHeader(directly or through one variable), or a@RequestParam/@PathVariable/@QueryParamint parameter. - Go: assigned from
strconv.Atoi/ParseInt/ParseUintoverr.URL.Query(),FormValue,Header.Get, ginc.Query/c.Param,mux.Varsoros.Args, directly or through one variable.
Not reported: a bound compared against a limit in an if before the loop, a bound clamped with min()/Math.min or a clamp helper, or passed to a verify/validate function, a loop in a different function from the parse, count-down loops over ntohs/ntohl values, a loop header with a second condition (i < n && i < MAX), constants, collection lengths and loops over collections.
Why This Matters
A caller who chooses the iteration count chooses how much CPU and memory the request costs. One request with rows=2000000000 keeps a worker busy for minutes.
What Gets Flagged
int rows = Integer.parseInt(request.getParameter("rows"));
for (int i = 0; i < rows; i++) {
raw := r.URL.Query().Get("times")
times, err := strconv.Atoi(raw)
for i := 0; i < times; i++ {
scanf("%u", &num);
for (unsigned int i = 0; i < num; i++) {
int times = atoi(argv[1]);
while (times-- > 0) {
Remediation
- Reject or clamp the value before the loop:
if (rows > MAX_ROWS) return error;orrows = Math.min(rows, MAX_ROWS);. - Prefer pagination over caller-chosen batch sizes.
- For a confirmed false positive, add a
// vulnetix-ignore: VNX-606comment on the line.
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-606
// nosec vnx-606
Or record an ignore rule: vulnetix ignore add --rule vnx-606 --reason "...". See Suppressing findings.