Laravel Insecure Random Numbers: How to Replace rand() and mt_rand() with Cryptographic Alternatives

Using rand() or mt_rand() for tokens, passwords, or security decisions creates predictable values that attackers can guess or reproduce.

Medium severity Application Security Updated 2026-05-01

The Problem

PHP's rand() and mt_rand() functions use predictable pseudo-random number generators (PRNGs). An attacker who observes a few outputs can predict future values — and in some cases, reconstruct past values. If you use these functions to generate password reset tokens, API keys, session identifiers, CSRF tokens, or any security-sensitive value, attackers can predict them and gain unauthorized access. PHP provides cryptographically secure alternatives that should always be used instead.

How to Fix

  1. 1

    Find insecure random usage in your code

    Search for rand() and mt_rand() in security-sensitive contexts:

    grep -rn 'rand(\|mt_rand(\|array_rand(\|shuffle(' app/ --include='*.php'

    Look specifically for usage in: - Token generation - Password/PIN creation - OTP codes - Nonce or salt generation - Random filename generation for uploads - Lottery/selection logic with financial impact

  2. 2

    Replace with cryptographically secure alternatives

    Use these replacements:

    // Random integers
    // BEFORE: rand(100000, 999999)
    // AFTER:
    random_int(100000, 999999);
    // Random strings/tokens
    // BEFORE: md5(mt_rand())
    // AFTER:
    Str::random(40);          // Laravel helper (uses random_bytes)
    bin2hex(random_bytes(20)); // Raw PHP
    // Random bytes
    // BEFORE: mt_rand() based
    // AFTER:
    random_bytes(32);
    // Shuffling arrays securely
    // BEFORE: shuffle($array)
    // AFTER: Use a Fisher-Yates shuffle with random_int()
  3. 3

    Use Laravel helpers for common patterns

    Laravel provides secure random generation out of the box:

    // Random string
    use Illuminate\Support\Str;
    Str::random(40);     // 40-char random string
    Str::uuid();         // UUID v4
    Str::orderedUuid();  // Time-ordered UUID
    // Token generation
    $token = hash('sha256', Str::random(60));
    // Unique filenames
    $filename = Str::uuid() . '.' . $file->extension();
    All of these use random_bytes() internally.

How to Verify

Search for remaining insecure usage:

grep -rn 'mt_rand(\|\brand(' app/ --include='*.php' | grep -v '// safe\|// non-security'

Run php artisan stackshield:scan --check=SS040 to verify.

Prevention

Use Str::random(), random_int(), or random_bytes() for all security-sensitive randomness. rand() and mt_rand() are acceptable only for non-security uses like UI element positioning or test data generation. Add a code review rule to flag rand()/mt_rand() usage.

Frequently Asked Questions

Is mt_rand() safe for non-security purposes?

Yes. For non-security uses like randomizing display order, generating test data, or adding visual variation, mt_rand() is fine. The key distinction is: will predictable values cause a security issue? If not, mt_rand() is acceptable and faster.

Is Str::random() cryptographically secure?

Yes. Laravel's Str::random() uses random_bytes() internally, which is cryptographically secure. It is safe for generating tokens, passwords, and other security-sensitive values.

Detect This Automatically with StackShield

StackShield continuously monitors your Laravel application from the outside and alerts you when security issues are found. No installation required.

Start Free Trial