VNX-192: Integer Coercion Error
Reports numbers parsed from text and converted to a narrower or unsigned type without a range check: Go int32/uint16(...) of strconv.Atoi/ParseInt results, Java (byte)/(short)/(int) casts of Integer.parseInt/Long.parseLong, and C/C++ narrow or unsigned variables initialised from atoi/strtol.
| Field | Value |
|---|---|
| Rule ID | VNX-192 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Go, Java, C, C++ |
| CWE | CWE-192 |
| CAPEC | CAPEC-128 |
| 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 | integer-coercion truncation sign-conversion cwe-192 |
| Source | internal/sast/rules/vnx-192.rego |
Overview
Converting a parsed number into a narrower or differently signed type silently truncates or flips its sign: 70000 becomes 4464 in an int16, -1 becomes 4294967295 in a uint32. A later bound, port, size or index check then sees a different value from the one supplied. This maps to CWE-192: Integer Coercion Error.
What Gets Flagged
limit, err := strconv.Atoi(r.URL.Query().Get("limit"))
rows := h.store.Page(int32(limit)) // flagged: 64-bit int to int32
v, _ := strconv.ParseInt(os.Getenv("PORT"), 10, 64)
port := uint16(v) // flagged
int level = Integer.parseInt(request.getParameter("level"));
byte b = (byte) level; // flagged
int size = (int) Long.parseLong(request.getParameter("size")); // flagged
short count = atoi(argv[1]); /* flagged */
uint16_t port = strtoul(argv[2], NULL, 10); /* flagged */
size_t len = atoi(argv[3]); /* flagged: negative becomes huge */
Not flagged: a conversion preceded by a comparison of the value (limit > math.MaxInt32, level > Byte.MAX_VALUE, v > UCHAR_MAX), Math.toIntExact, conversions to the same or a wider type, and ParseInt/ParseUint called with a bit size that already fits the target. JavaScript, PHP, Python and Ruby are not covered: their integers do not coerce this way.
Remediation
p, err := strconv.ParseUint(s, 10, 16) // parse with the target's bit size
port := uint16(p)
int level = Integer.parseInt(raw);
if (level < Byte.MIN_VALUE || level > Byte.MAX_VALUE) throw new IllegalArgumentException();
byte b = (byte) level;
References
- CWE-192
- SEI CERT INT31-C: Ensure that integer conversions do not result in lost or misinterpreted data
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-192
// nosec vnx-192
Or record an ignore rule: vulnetix ignore add --rule vnx-192 --reason "...". See Suppressing findings.