A04: Cryptographic Failures
What is a cryptographic failure?
Cryptographic Failures happen when an application mishandles secrets, encryption, hashing, or key management in a way that exposes data.
Laravel 12 documents application key usage and supports previous keys via APP_PREVIOUS_KEYS; it also provides encryption services and secure hashing with Bcrypt and Argon2.
Typical Laravel failure
- Storing secrets or tokens in plain text.
- Encrypting inconsistently.
- Weak key management.
- Confusing hashing with encryption.
- Rotating keys badly.
Impact
- Credential disclosure (passwords, API tokens) and account takeover.
- Sensitive data exposure (PII, financial data) if encryption is missing or broken.
- Permanent loss of access to encrypted data after bad key rotation.
- Incident amplification when secrets appear in logs.
Laravel 12 remediation
- Use
Hashfor passwords (one-way), never encryption. - Use
Cryptonly for decryptable sensitive values. - Protect and rotate
APP_KEYcorrectly. - Use
APP_PREVIOUS_KEYSduring rotation to avoid breaking old encrypted values. - Never log secrets, OTP seeds, reset tokens, API tokens, or raw personal data.
Concrete fix
Rotate APP_KEY safely using APP_PREVIOUS_KEYS so old encrypted values can still be decrypted:
# .env (example) # New keyAPP_KEY=base64:NEW_KEY_HERE # One or more old keys, comma-separatedAPP_PREVIOUS_KEYS=base64:OLD_KEY_1,base64:OLD_KEY_2
Hash passwords:
use Illuminate\Support\Facades\Hash; $password = Hash::make($request->password);
Encrypt decryptable sensitive values:
use Illuminate\Support\Facades\Crypt; $encrypted = Crypt::encryptString($sensitiveValue);
Design pattern angle
Centralize crypto behind a small service/port so you can standardize algorithms, add key-rotation behavior, and swap Laravel Crypt for a KMS/HSM-backed implementation later.
Avoid scattering Crypt::encryptString(...) across controllers and models.
interface SensitiveValueCipher{ public function encrypt(string $plain): string; public function decrypt(string $cipher): string;} final class LaravelCipher implements SensitiveValueCipher{ public function encrypt(string $plain): string { return \Illuminate\Support\Facades\Crypt::encryptString($plain); } public function decrypt(string $cipher): string { return \Illuminate\Support\Facades\Crypt::decryptString($cipher); }}