ALL-SECU0003 · unseeded_randomness_for_secrets
Count the unguessable values an ordinary random generator produced.
This is a deterministic rule for all languages. Read its implementation.
Definition
Section titled “Definition”Read every binding whose name promises a value nobody may predict, such as a token, a nonce,
a session id, or an api key, then report the calls beneath it that reach a general purpose
pseudo random generator. random, Math.random, rand, srand, and thread_rng all run a
fast deterministic sequence that an observer recovers after collecting a handful of outputs,
so a token minted from one is guessable by anyone patient enough to collect them. The cost
arrives as account takeover rather than as a crash a test would have caught, which is why no
amount of later testing finds it.
Evidence
Section titled “Evidence”Each finding names the declaration, the bound name, and the generator the call reaches. The value is how many predictable draws land under a name that promised secrecy.
Exceptions
Section titled “Exceptions”Randomness that guards nothing is fine, so a retry delay, a sampled batch, or a test fixture
is never reported, because the name never claimed the value had to be unguessable. A
generator built for secrets, such as secrets, os.urandom, crypto.getRandomValues, or
SecureRandom, is the answer this rule asks for and stays welcome even under a secret name.
A bare key is a map key far more often than a credential, so it takes a qualifier to count.
A project with its own wrapper around an ordinary generator names it through
also_predictable.
Examples
Section titled “Examples”const sessionToken = Math.random().toString(36).slice(2)const sessionToken = crypto.randomUUID()References
Section titled “References”- Generalizes Ruff S311 suspicious-non-cryptographic-random-usage. Open reference
- Cites “Common Weakness Enumeration”, CWE-338, weak pseudo random number generation. Open reference
- Cites “The Python Standard Library”,
secrets, secure random numbers. Open reference