VNX-340: Generation of Predictable Numbers or Identifiers
Detects secrets produced by predictable identifier generators: time-based UUIDs (v1/v6), name-based UUIDs (v3/v5) and PHP uniqid(), when stored under, keyed by or returned as a secret. Python, JavaScript/TypeScript, PHP, Go, Java, Kotlin and Ruby.
| Field | Value |
|---|---|
| Rule ID | VNX-340 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Python, JavaScript / TypeScript, PHP, Go, Java, Kotlin, Ruby |
| CWE | CWE-340 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | randomness predictable uuid cwe-340 |
| Source | internal/sast/rules/vnx-340.rego |
Overview
VNX-340 maps to CWE-340: Generation of Predictable Numbers or Identifiers. Some identifier generators are unique but not unpredictable. A version 1 or 6 UUID is a timestamp plus the host’s MAC address or a fixed node id; a version 3 or 5 UUID is a hash of its input, so anyone who knows the input (an email address, a user name) computes the same value; PHP uniqid() is the current time in hex. None of them is a secret.
The rule reports uuid.uuid1()/uuid3()/uuid5(), JavaScript uuid v1/v3/v5/v6, Ramsey Uuid::uuid1()/uuid3()/uuid5()/uuid6(), Go uuid.NewUUID()/NewMD5/NewSHA1 and gofrs NewV1/NewV3/NewV5/NewV6, Java UUID.nameUUIDFromBytes() and the time- and name-based generators of java-uuid-generator and UuidCreator, Ruby Digest::UUID.uuid_v3/uuid_v5 and UUIDTools timestamp_create/md5_create/sha1_create, and PHP uniqid(), when the result is stored under, keyed by or returned as a secret (token, password, secret, nonce, salt, OTP, CSRF, session id, API key, reset/confirmation/invite code, session cookie), directly or through a variable that reaches such a name within six lines.
What Gets Flagged
# FLAGGED: time-based and name-based UUIDs as secrets
session_id = str(uuid.uuid1())
def new_reset_token(user):
return uuid.uuid5(uuid.NAMESPACE_DNS, user.email).hex
// FLAGGED: uniqid() is the clock
$_SESSION['session_token'] = md5(uniqid());
// FLAGGED: a hash of the email address
String resetToken = UUID.nameUUIDFromBytes(email.getBytes(StandardCharsets.UTF_8)).toString();
What Is Not Flagged
- Random UUIDs:
uuid4(),crypto.randomUUID(),UUID.randomUUID(),uuid.New(),SecureRandom.uuid,Uuid::uuid4(). uniqid()and time-based UUIDs used as file names, request ids, cache keys and other identifiers that are not secrets.- Values combined on the same line with a CSPRNG (
random_bytes,secrets,crypto.randomBytes), test files, and the call in comments or string literals.
Remediation
- Use a random (version 4) UUID or, better, a CSPRNG token of at least 128 bits:
secrets.token_urlsafe(32),crypto.randomBytes(32),bin2hex(random_bytes(32)),SecureRandom.urlsafe_base64(32). - For confirmed false positives, add a
# vulnetix-ignore: VNX-340comment on the line.
References
- CWE-340: Generation of Predictable Numbers or Identifiers
- RFC 9562, Universally Unique IDentifiers: Security Considerations
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-340
// nosec vnx-340
Or record an ignore rule: vulnetix ignore add --rule vnx-340 --reason "...". See Suppressing findings.