Skip to content

Application Key Analyzer

Analyzer IDCategorySeverityTime To Fix
app-key🛡️ SecurityCritical5 minutes

What This Checks

Validates that Laravel's APP_KEY encryption key is properly configured and secure in your .env file and config/app.php. Checks for:

  • Missing or empty APP_KEY in .env
  • Placeholder/example values (e.g., "your-key-here")
  • Weak key formats (too short or improperly encoded)
  • Duplicate APP_KEY definitions in .env
  • Hardcoded keys in config/app.php (should use env())
  • Insecure cipher algorithms

Why It Matters

  • Security Risk: HIGH - The APP_KEY is used for all encryption in Laravel (sessions, cookies, encrypted data)
  • Data Loss: If APP_KEY changes, all encrypted data becomes permanently unreadable
  • Session Security: Weak or default keys allow attackers to forge sessions and impersonate users
  • CSRF Protection: Laravel's CSRF tokens depend on APP_KEY for cryptographic signing

How to Fix

Quick Fix (1 minute)

Scenario 1: Missing or Empty APP_KEY

bash
# Generate a secure key
php artisan key:generate

# This updates your .env file with a secure base64-encoded key
# APP_KEY=base64:RANDOM_32_BYTE_STRING_HERE

Scenario 2: Placeholder Value (from .env.example)

bash
# Remove the placeholder and generate a real key
php artisan key:generate --force

Scenario 3: Configuration is Cached

bash
# Clear the cache to allow .env changes to take effect
php artisan config:clear

# After making changes, recache for production
php artisan config:cache

Proper Fix (5 minutes)

Implement comprehensive APP_KEY security across all environments:

1. Generate and Store Keys Securely

bash
# Generate key for each environment
php artisan key:generate

# For production, store in environment variables
# Laravel Forge/Vapor:
# - Add APP_KEY to environment variables in dashboard

# Traditional servers:
# - Add to web server environment config
# - Or use encrypted .env files

2. Environment-Specific Key Management

bash
# Development (.env) - Use a unique key for local development
APP_KEY=base64:LOCAL_DEV_KEY_HERE

# Production/Staging - Manage through deployment process
# - Use CI/CD environment variables
# - Use secrets managers (AWS Secrets Manager, Vault, etc.)
# - Use platform environment config (Laravel Forge, Vapor, etc.)

# Important: Production and staging should typically use the SAME key
# if you share encrypted data between them (e.g., database backups)

3. Never Commit Real Keys to Git

ini
# .env.example - Use placeholders only
APP_NAME=Laravel
APP_ENV=production
APP_KEY=base64:your-key-here
APP_DEBUG=false
APP_URL=https://yourapp.com

4. Handle Key Rotation Carefully

php
// If you must rotate keys, decrypt with old key and re-encrypt with new key
// Don't do this unless absolutely necessary (security breach, etc.)

use Illuminate\Support\Facades\Crypt;
use Illuminate\Encryption\Encrypter;

// 1. Backup database first!

// 2. Create encrypter with old key
$oldEncrypter = new Encrypter(
    base64_decode(substr('base64:OLD_KEY', 7)),
    config('app.cipher')
);

// 3. Decrypt and re-encrypt each encrypted field
$users = DB::table('users')->select('id', 'encrypted_field')->get();

foreach ($users as $user) {
    $decrypted = $oldEncrypter->decrypt($user->encrypted_field);
    $reencrypted = Crypt::encrypt($decrypted);  // Uses new key from config

    DB::table('users')
        ->where('id', $user->id)
        ->update(['encrypted_field' => $reencrypted]);
}

5. Validate Key Format

Ensure your key matches Laravel's expected format:

php
// Valid formats:

// Base64-encoded (recommended - generated by key:generate)
APP_KEY=base64:/AvmHMmBChdiKxwxReS4zWfHKXAfl0vsbJIf2fT3gHA=

// Raw 32-character string (legacy, not recommended)
APP_KEY=SomeRandomStringWith32Characters!

// The base64 format should decode to at least 16 bytes (AES-128)
// or 32 bytes (AES-256)

6. Production Deployment Checklist

bash
# Before deploying to production:

# 1. Verify APP_KEY is set
php artisan tinker
>>> config('app.key')
// Should output a key, not null

# 2. Verify key length
>>> strlen(base64_decode(substr(config('app.key'), 7)))
// Should be 16 (AES-128) or 32 (AES-256)

# 3. Test encryption/decryption
>>> encrypt('test')
>>> decrypt(encrypt('test'))
// Should return 'test'

# 4. Check cache status
>>> app()->configurationIsCached()
// Should be true in production

# 5. If cached, verify cached key matches .env
cat bootstrap/cache/config.php | grep 'key'

ShieldCI Configuration

This analyzer is automatically skipped in CI environments ($runInCI = false).

Why skip in CI?

  • CI environments typically use test/placeholder keys for running tests
  • Real production keys should never be in the repository or CI environment
  • Prevents false failures in CI pipelines where placeholder keys are expected

When to run this analyzer:

  • Local development: Ensures developers have proper keys configured
  • Staging/Production servers: Validates environment-specific keys are secure
  • CI/CD pipelines: Skipped automatically (test keys are expected)

References