insecure-randomness
Skill2 starsChanged 4 months agoMITView on GitHub
SAST detection methodology for insecure randomness (CWE-330, CWE-338, CWE-331), where security-sensitive values (session IDs, password-reset/OTP/CSRF tokens, API keys, coupon codes) are generated with a non-CSPRNG (Math.random, java.util.Random, rand, mt_rand, Python random), a predictable seed, UUIDv1, or insufficient entropy. Use when reviewing code that generates tokens, IDs, keys, or nonces. Writes confirmed findings to findings/29-insecure-randomness.md.
In this repository49 other files it gives its agents.
- authentication-flawsSkill
- broken-access-control-idorSkill
- business-logic-flawsSkill
- cicd-and-pipeline-injectionSkill
- code-injectionSkill
- command-injectionSkill
- cors-misconfigurationSkill
- crlf-and-header-injectionSkill
- cross-site-scriptingSkill
- csrfSkill
- dependency-and-supply-chainSkill
- dom-clobbering-and-postmessageSkill
- graphql-injection-and-abuseSkill
- hardcoded-secretsSkill
- http-request-smugglingSkill
- iac-misconfigurationSkill
- information-disclosureSkill
- insecure-deserializationSkill
- jwt-vulnerabilitiesSkill
- ldap-injectionSkill
- llm-and-ai-application-securitySkill
- mass-assignmentSkill
- memory-safetySkill
- mobile-android-securitySkill
- mobile-ios-securitySkill
- nosql-injectionSkill
- oauth-oidc-saml-flawsSkill
- open-redirectSkill
- path-traversal-and-file-inclusionSkill
- prototype-pollutionSkill
- race-conditions-and-toctouSkill
- redosSkill
- sast-final-reportSkill
- sast-finding-validationSkill
- sast-methodologySkill
- security-logging-and-monitoring-failuresSkill
- security-misconfiguration-and-headersSkill
- server-side-template-injectionSkill
- session-managementSkill
- smart-contract-securitySkill
- sql-injectionSkill
- ssrfSkill
- unrestricted-file-uploadSkill
- unsafe-parsers-and-yamlSkill
- weak-cryptographySkill
- web-cache-poisoning-and-deceptionSkill
- websocket-securitySkill
- xpath-and-xml-injectionSkill
- xxeSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 3 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 42
Not a taint-flow class. The signal is a weak RNG API whose output flows into a security-sensitive consumer.
- Distinctive: line 100
Use ≥128 bits of entropy for tokens/keys.
- Distinctive: line 112
Only random-based UUIDv4 (from a CSPRNG) is unpredictable.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Insecure Randomness — SAST Methodology
Class: Insecure Randomness · CWE-330 · OWASP: A02 Cryptographic Failures
Findings file: findings/29-insecure-randomness.md
1. Overview
Insecure randomness exists when a value that must be unguessable — a token,
session ID, key, nonce, OTP, or reset code — is produced by a non-cryptographic
PRNG or with insufficient entropy, so an attacker can predict past/future outputs
or brute-force the value. General PRNGs (Math.random, java.util.Random, C
rand, Python random, PHP mt_rand) are statistically uniform but
deterministic and state-recoverable: observing a few outputs (or knowing the
seed) reveals the rest. The core test: does a value that gates security flow from a
non-CSPRNG, a predictable/time-based seed, a non-random source like UUIDv1, or too
few bits of entropy?
2. Where it lives
- Session/CSRF token generation; password-reset and email-verification tokens; OTP/2FA codes; magic-link and invitation codes.
- API key / client-secret / device-token generation; coupon/voucher/gift-card codes; account/order reference numbers used as capabilities.
- OAuth
state/PKCE verifier, nonce generation; temp-file and upload names that must be unguessable; IV/nonce/salt generation (overlaps weak-crypto). - Homemade "random string" / "generate token" helpers built on the language's default PRNG.
3. Sources (tainted input)
Not a taint-flow class. The signal is a weak RNG API whose output flows into a
security-sensitive consumer. Identify (a) the generator — a non-CSPRNG call or a
CSPRNG that was seeded predictably — and (b) the consumer — a token/ID/key/nonce
that must be unguessable. Exploitability depends on the attacker's ability to
observe prior outputs (to recover PRNG state) or to know/narrow the seed (e.g. a
time()-based seed the attacker can bound), and on the value's entropy/length.
4. Sinks (dangerous operations)
// Node / browser — dangerous
const token = Math.random().toString(36).slice(2); // xorshift128+, recoverable
const otp = Math.floor(Math.random() * 1000000); // predictable 6-digit OTP
const id = Date.now() + '' + Math.random(); // time + weak PRNG// Java — dangerous
new Random().nextInt(); // 48-bit LCG, fully predictable
String t = Long.toHexString(new Random(seed).nextLong()); // known/derivable seed
UUID.randomUUID(); // OK (CSPRNG-backed) — but time-based UUIDs are NOT:# Python — dangerous
import random
token = ''.join(random.choice(string.ascii_letters) for _ in range(16)) # MT19937
reset = random.randint(100000, 999999) # predictable OTP
random.getrandbits(128) # not for secrets// PHP — dangerous
$token = md5(uniqid()); // uniqid = microtime, low entropy, guessable
$code = mt_rand(100000, 999999); // Mersenne Twister, seed brute-forceable
$key = rand(); // very weak// C — dangerous
srand(time(NULL)); int t = rand(); // seed = wall clock, tiny state// Go — dangerous
import "math/rand"
rand.Int63() // deterministic; use crypto/rand for secretsDangerous whenever the generated value gates security and the generator is any of the above rather than a CSPRNG.
5. Sanitizers / safe patterns
Safe (CSPRNGs):
- Python:
secrets.token_urlsafe/token_hex/token_bytes,secrets.randbelow,os.urandom. - Node:
crypto.randomBytes,crypto.randomUUID(),crypto.randomInt, browsercrypto.getRandomValues. - Java:
java.security.SecureRandom(default constructor /getInstanceStrong) — never seeded with a fixed/known value. - Go:
crypto/rand(rand.Read). PHP:random_bytes,random_int. - C / Linux:
getrandom(2)or/dev/urandom. - Use ≥128 bits of entropy for tokens/keys; for numeric OTPs, compensate short length with strict rate-limiting, expiry, and lockout.
Fails / not a real sanitizer:
- Seeding a CSPRNG predictably —
SecureRandomthensetSeed(fixedValue), or seeding any PRNG withtime()/PID/counter, collapses entropy to a guessable space. - Hashing a weak-PRNG output —
md5(mt_rand()),sha1(uniqid()): a hash of a predictable input is still predictable (just recover the input and re-hash). - CSPRNG but truncated / small space — a strong RNG cut to 4–6 chars or a 6-digit code without rate-limiting is brute-forceable.
- UUIDv1 as a secret — encodes timestamp + MAC/clock-seq, not random; guessable. Only random-based UUIDv4 (from a CSPRNG) is unpredictable.
uniqid()used as a token — it is microtime with tiny entropy, even withmore_entropy=true.- Reusing one nonce/IV from any generator (overlaps weak-crypto).
6. Detection methodology
- Find weak generators.
rg -n 'Math\.random\(' rg -n 'new Random\(|java\.util\.Random|\.nextInt\(|\.nextLong\(|\.nextDouble\(' rg -n '\brand\(|srand\(|\bmt_rand\(|mt_srand\(|\buniqid\(|lcg_value\(' rg -n '\brandom\.(random|randint|randrange|choice|getrandbits|sample|shuffle)\(' rg -n 'math/rand|rand\.Int|rand\.Int63|rand\.Seed' rg -n 'uuid1\(|UUID\.fromString|type[ =]*1|time_low' # time-based UUID as secret - Trace the output to a consumer: does it become a session ID, reset/OTP/CSRF token, API key, nonce, coupon, or unguessable filename?
- Check the seed: is the PRNG seeded from
time()/PID/a constant, or a CSPRNG mis-seeded viasetSeed? - Estimate the effective search space: token length × charset, or the seed space the attacker can bound; and whether prior outputs are observable (state recovery).
- Confirm reachability & observability: can an attacker request tokens and see outputs, or repeatedly guess (no rate limit)?
- Classify: predictable secret (state/seed recovery) vs brute-forceable (insufficient entropy) — both are findings.
7. Modern & niche variants
Math.random()for tokens: V8'sxorshift128+internal state is fully recoverable from a handful of consecutive outputs, letting an attacker predict every subsequent token from the same context. Never for anything security-bearing.java.util.Random: a 48-bit linear congruential generator — the full state is recoverable from one or two outputs, making all future values predictable.- C
rand()/ predictable seed: small internal state and typicallysrand(time(NULL))— the seed is the wall clock, brute-forceable in a narrow window. - PHP
rand/mt_rand/uniqid:mt_randis a Mersenne Twister whose seed can be brute-forced (historically from a couple of outputs);uniqid()is microtime-derived with tiny entropy;md5(uniqid())reset tokens are a classic account-takeover bug. - Python
randomfor secrets: MT19937 — its entire 19937-bit state is recoverable from 624 consecutive 32-bit outputs, exposing all future values. Usesecrets/os.urandominstead. - Predictable / time-based seeds: any generator seeded from
time(), PID, request counter, or process start time — the attacker bounds the seed and replays the sequence. - Security values from a non-CSPRNG: session IDs, password-reset tokens, OTPs, CSRF tokens, API keys, and coupon codes generated with the above — the highest- impact case, since predicting one enables account takeover or fraud.
- UUIDv1 as a secret: time + MAC address (+ clock sequence) — structured and
guessable; distinct from UUIDv4. Flag
uuid1()/version-1 UUIDs used where unpredictability is required. - Insufficient entropy / length: even a CSPRNG yields a weak token if truncated to a few characters or a short numeric OTP without rate-limiting — a brute-force target.
8. Common false positives
- Non-security randomness: shuffling display order, sampling, jitter/backoff, load-balancing, cache-busters, A/B bucketing, test-data generation, game mechanics — a fast PRNG is appropriate there.
- CSPRNG-backed generators:
crypto.randomUUID(),uuid4()from a CSPRNG, JavaSecureRandom(unseeded), Gocrypto/rand,secrets/random_bytes. - Short OTPs that are strongly rate-limited, single-use, and short-expiry — weaker but mitigated (note, lower severity).
- A weak-PRNG value that is combined with, or replaced by, sufficient CSPRNG entropy before use.
9. Severity & exploitability
Base Medium. High when the predicted/brute-forced value directly enables
account or session compromise — a password-reset token, session ID, API key, or
2FA/OTP code from a non-CSPRNG or with insufficient entropy. Can reach Critical
via chain (predict a reset token → account takeover of any user; predict admin
session IDs). Raise for pre-auth reachability, observable prior outputs, and no
rate limiting; lower for non-secret uses or well-mitigated short OTPs. See
references/severity-model.md.
10. Remediation
Generate every security-sensitive value with a CSPRNG (secrets,
crypto.randomBytes/randomUUID, SecureRandom, crypto/rand, random_bytes,
getrandom) and never seed it from a predictable value. Use ≥128 bits of entropy
for tokens/keys and random-based UUIDv4 rather than v1. For short numeric codes,
add strict rate-limiting, single use, and short expiry. Do not hash a weak-PRNG
output and call it random. Keep fast PRNGs strictly for non-security use.
11. Output
Append each confirmed finding to findings/29-insecure-randomness.md using
references/finding-template.md. Set Class: Insecure Randomness and
CWE: CWE-330 (use CWE-338 for use of a non-crypto PRNG in a security context,
CWE-331 for insufficient entropy). In Chain potential name primitives such as
predictable token (reset/verify/OTP → account takeover, the terminal
primitive of an auth chain), session prediction (→ session hijack), predictable
nonce/IV (feeds the weak-crypto forgery chain), and guessable capability (coupon/
reference-number fraud). Note when the finding consumes an information-leak
primitive that exposes prior RNG outputs or the seed.
Primitives (controlled): provides IDENTITY_FORGE,SECRET_LEAK (predictable token); consumes none
References
- CWE-330 Use of Insufficiently Random Values; CWE-338 Use of Cryptographically Weak PRNG; CWE-331 Insufficient Entropy; OWASP A02:2021 Cryptographic Failures; OWASP Testing Guide — Testing for Weak Randomness; NIST SP 800-90A/B.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

