Safeguard
Application Security•

ASVS 5.0 V11.5.1: Generate Secrets With a CSPRNG

ASVS V11.5.1 requires non guessable values from a CSPRNG with at least 128 bits of entropy, and says UUIDs do not qualify. Safe code for four languages.

Safeguard Security Team
3 min read

ASVS 5.0 V11.5.1 (Level 2) requires that every random number or string meant to be non guessable comes from a cryptographically secure pseudo random number generator (CSPRNG) and carries at least 128 bits of entropy. The standard notes explicitly that UUIDs do not satisfy this.

Why it matters

Session ids, password reset tokens, API keys, invitation links and CSRF tokens all rely on being unpredictable. A general purpose generator such as Math.random or java.util.Random can be reconstructed from a few outputs. After that, an attacker predicts the next token and takes over accounts.

UUIDs are the surprise. Version 1 embeds a timestamp and a machine id. Version 4 is random in design, but the standard does not guarantee which generator an implementation uses or how many bits are random, and only 122 are. Use a purpose built secret instead.

How to implement it

Use the operating system CSPRNG through the standard library, and request at least 16 bytes (128 bits), commonly 32.

import secrets
token = secrets.token_urlsafe(32)   # 256 bits
import { randomBytes } from 'node:crypto';
const token = randomBytes(32).toString('base64url');
SecureRandom rng = new SecureRandom();
byte[] b = new byte[32];
rng.nextBytes(b);
String token = Base64.getUrlEncoder().withoutPadding().encodeToString(b);
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil { return "", err }  // crypto/rand
return base64.RawURLEncoding.EncodeToString(b), nil

Wrap this in one function named for its purpose, such as new_secret_token(), and ban the weak generators in lint rules. If the random call fails, return an error. Never fall back to a time based value.

Store tokens carefully too. For reset links and API keys, keep only a hash of the token in your database, so a leaked table does not hand out live credentials. Since the token has high entropy, a fast hash such as SHA-256 is fine for this case, unlike passwords.

Check lengths against the entropy rule. A 6 digit code has about 20 bits, which is fine for a short lived second factor with strict rate limits, but never acceptable as a standalone session secret.

Try it yourself

Click through it at your own pace, or open it full screen.

How to test it

Static: search for Math.random, random.random, java.util.Random, rand(), uuid1, uuid4 and Date.now near the words token, secret, session, key, reset or invite. Each hit is a finding unless the value is not security relevant.

Dynamic: request 10,000 tokens from the running app. Check that none repeat, that lengths match the design, and that character frequencies look flat. Tools that estimate entropy from a sample can flag obvious structure such as counters or timestamps.

Also confirm the encoded length. Base64url of 16 bytes is 22 characters; a 22 character hex string holds only 88 bits.

Common mistakes

  • Using UUIDs as session or reset tokens
  • Seeding a normal generator with the current time
  • Encoding as hex and counting characters instead of bits
  • Truncating a token to make a link look shorter
  • Storing raw reset tokens in the database

Quick check

Do UUIDs meet V11.5.1?

No. The standard says UUIDs do not respect the entropy and generator condition.

How many bytes give 128 bits?

Sixteen bytes from a CSPRNG, though 32 is a common choice.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.