VNX-229: Improper Handling of Values
A request value is converted to a number with no handling of a missing or malformed value: Python int()/float() of a request value outside try, or Node.js parseInt/parseFloat/Number of req.query or req.body whose NaN is never handled.
| Field | Value |
|---|---|
| Rule ID | VNX-229 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | JavaScript / TypeScript, Python |
| CWE | CWE-229 |
| 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 | improper-handling-of-values cwe-229 input-validation |
| Source | internal/sast/rules/vnx-229.rego |
Overview
VNX-229 maps to CWE-229: Improper Handling of Values. It reports a request value converted to a number where a missing or malformed value is not handled:
- Python:
int()orfloat()applied to a Flask, Django or DRF request value (request.args,form,values,GET,POST,json,get_json(),data,cookies,headers,query_params), inline or through a variable assigned from one in the eight lines above, outside anytryblock. - Node.js / TypeScript:
parseInt(),parseFloat()orNumber()ofreq.queryorreq.body(inline, or through an assigned or destructured variable) whose result is neither defaulted on the same line (||,??) nor tested withisNaN,Number.isNaN,isFiniteorNumber.isIntegerin the lines that follow.
Why This Matters
In Python a missing parameter raises TypeError and a non-numeric one ValueError, so any client can turn the endpoint into a 500; float() also accepts "nan" and "inf", which then poison arithmetic such as balances and discounts. In JavaScript the conversion never fails: it yields NaN, which flows into queries and calculations.
Not reported: Flask’s get(..., type=int), a conversion inside try or with contextlib.suppress(...), a value guarded by isdigit()/isnumeric()/isdecimal() or a regex match just above, route parameters (req.params, constrained by the route pattern), constants and environment values, commented-out code and string literals.
What Gets Flagged
src.balance -= int(request.form['amount'])
page = request.GET.get("page", 1)
offset = (int(page) - 1) * 20
const limit = parseInt(req.query.limit, 10);
const items = await Item.find().limit(limit);
Remediation
page = request.args.get("page", 1, type=int)
try:
amount = int(request.form["amount"])
except (TypeError, ValueError):
abort(400)
const limit = parseInt(req.query.limit, 10);
if (Number.isNaN(limit)) return res.status(400).send("bad limit");
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-229
// nosec vnx-229
Or record an ignore rule: vulnetix ignore add --rule vnx-229 --reason "...". See Suppressing findings.