VNX-1284: Improper Validation of Specified Quantity in Input
A quantity the client chose (a request field named quantity, qty, amount, units, credits, points, coins, num_items, deposit or withdraw/withdrawal) is used in a balance, stock or price calculation, or stored on an order, cart or wallet record, with no check that it is positive and within limits, so a negative or huge value moves money the wrong way, creates stock or overflows a total. Reported in Python (Flask/Django/DRF request.args/form/values/json/GET/POST/data/query_params) and JavaScript/TypeScript (req.body/query/params, including const { quantity } = req.body): the value, inline or through a variable assigned from it in the 20 lines above (including a TypeScript-annotated const), used in x += / -= / *= arithmetic, a $inc update, a multiplication, an x = y + / - arithmetic assignment, or as a quantity-named field (or shorthand property) of an ORM create/update/insert/save/build/upsert, $inc or $set. Not reported: a comparison of the value (<, <=, >, >=, in range(...)) or a max()/abs()/clamp/positive check between the read and the use, a file that validates with a schema (Joi/yup/zod .positive() or .min(0|1), pydantic conint/confloat/PositiveInt/gt=0/ge=1, express-validator isInt/isFloat({ min | gt })), the local assignment that reads the value, a value that is only displayed, counts and page sizes (judged by VNX-400 and VNX-606), a client amount credited to a balance or booked as an order total that VNX-840 reports (Client-Controlled Monetary Value, such as dst.balance += int(request.form["amount"]) or { $inc: { balance: -amount } } in a payment or wallet handler): that line is reported by VNX-840, so the negative-amount transfer is one finding rather than two, and text in comments and strings.
| Field | Value |
|---|---|
| Rule ID | VNX-1284 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | JavaScript / TypeScript, Python |
| CWE | CWE-1284 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | improper-validation-of-specified-quantity business-logic cwe-1284 |
| Source | internal/sast/rules/vnx-1284.rego |
Overview
VNX-1284 maps to CWE-1284: Improper Validation of Specified Quantity in Input.
Why This Matters
A quantity or amount taken from the request and used as is lets the client choose a negative or huge value. A negative transfer moves money the wrong way, a negative cart quantity gives a refund, and a huge one overflows a total or exhausts stock.
What Gets Flagged
product.stock += int(request.form["quantity"])
qty = int(request.POST.get("quantity", 1))
total = product.price * qty
const { productId, quantity } = req.body;
await CartItem.create({ productId, quantity });
const { points } = req.body;
await Member.updateOne({ _id: id }, { $inc: { points: -points } });
Not flagged: a value compared (if amount <= 0 or amount > src.balance: abort(400)) or clamped (max(1, ...)) before use, a file that validates with a schema (Joi.number().positive(), pydantic conint(gt=0)), a value that is only displayed.
A client amount credited to a balance or booked as an order total (dst.balance += int(request.form["amount"]), account.balance -= amount, { $inc: { balance: -amount } } in a wallet or payment handler) is reported by VNX-840 (Client-Controlled Monetary Value), not here as well: the negative or oversized amount is how that one defect is exploited, so it is one finding. Quantities, units, credits, points and stock, and money values VNX-840 does not take, stay here.
Remediation
- Reject quantities below the minimum (usually 1) and above a business maximum before using them.
- Validate request bodies with a schema that states the range.
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-1284
// nosec vnx-1284
Or record an ignore rule: vulnetix ignore add --rule vnx-1284 --reason "...". See Suppressing findings.