VNX-334: Small Space of Random Values
Reports secrets drawn as a random integer from fewer than 2^32 values (random.randint, secrets.randbelow, nextInt, crypto.randomInt, Math.random() * N, PHP random_int/mt_rand, Ruby rand/SecureRandom.random_number) when the value is named as a token, secret, key, session id or reset value. OTPs and PINs are not reported.
| Field | Value |
|---|---|
| Rule ID | VNX-334 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Java, Kotlin, JavaScript / TypeScript, PHP, Python, Ruby |
| CWE | CWE-334 |
| 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 | small-random-space cwe-334 crypto |
| Source | internal/sast/rules/vnx-334.rego |
Overview
VNX-334 maps to CWE-334: Small Space of Random Values. It reports a secret drawn as a random integer from a range of fewer than 2^32 values, when the same line names it as a token, secret, key, password, salt, session id, CSRF, API key, reset or invite value.
Why This Matters
However good the generator, a value chosen from a million possibilities is guessed in a million tries, and often far fewer when the attacker can try many tokens at once. Session ids and reset tokens need at least 128 bits.
What Gets Flagged
# FLAGGED
session_id = random.randint(1000, 9999)
reset_token = secrets.randbelow(1000000)
// FLAGGED: nextInt() is 32 bits at most, even from SecureRandom
int sessionId = rnd.nextInt(100000);
// FLAGGED
const resetToken = crypto.randomInt(100000, 999999);
const sessionId = Math.floor(Math.random() * 1000000);
What Is Not Flagged
- Bounds from variables or expressions, and ranges of 2^32 and more (
secrets.randbelow(2**128)). - Random integers with no security name: indexes, delays, ports, colours, dice.
- One-time passcodes and PINs: a 6-digit OTP is the norm and is protected by expiry and attempt limits.
- Comments and test files.
Remediation
Generate tokens from at least 128 random bits: secrets.token_urlsafe(32), crypto.randomBytes(32).toString('hex'), or 16+ bytes from SecureRandom.nextBytes.
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-334
// nosec vnx-334
Or record an ignore rule: vulnetix ignore add --rule vnx-334 --reason "...". See Suppressing findings.