Laravel Unsafe Deserialization: How to Eliminate unserialize() and Prevent Object Injection
PHP unserialize() with user-controlled data enables remote code execution through object injection. Replace with json_decode() or add allowed_classes restrictions.
The Problem
PHP's unserialize() function reconstructs objects from serialized strings. If an attacker can control the serialized data, they can instantiate arbitrary classes and trigger their __wakeup() or __destruct() methods — leading to remote code execution, file deletion, or database manipulation. This is called PHP Object Injection and is rated critical because it often leads to full server compromise. Laravel internally uses serialization for queued jobs and cache, but these are protected by encryption. The danger is when your code calls unserialize() on user-supplied input.
How to Fix
-
1
Find all unserialize() calls
Search your codebase:
grep -rn 'unserialize(' app/ routes/ --include='*.php'Also search for related functions:
grep -rn 'unserialize\|deserialize\|object_decode' app/ --include='*.php'For each occurrence, trace whether the input could originate from a user request, database field populated by users, cache, or external API.
-
2
Replace with json_decode() where possible
Most serialized data can use JSON instead:// BEFORE — unsafe $data = unserialize($request->input('data'));// AFTER — safe $data = json_decode($request->input('data'), true);JSON cannot instantiate PHP objects, eliminating the object injection vector entirely. Update both the serialization and deserialization sides:
// Saving $encoded = json_encode($data);// Loading $decoded = json_decode($encoded, true); -
3
If unserialize() is unavoidable, restrict allowed classes
PHP 7+ supports an allowed_classes option:
// Only allow specific classes $data = unserialize($serialized, [ 'allowed_classes' => [MyDTO::class, Collection::class], ]);// Or allow no classes at all (safest) $data = unserialize($serialized, [ 'allowed_classes' => false, ]);With allowed_classes set to false, any serialized objects are converted to __PHP_Incomplete_Class, preventing method execution.
How to Verify
Run the scanner:
php artisan stackshield:scan --check=SS043
Manually test: if your application accepts serialized data via any input, try sending a crafted payload and verify the application rejects it or handles it safely.
Prevention
Default to JSON for all data serialization. Never call unserialize() on user input. If you must deserialize, always use the allowed_classes option. Laravel's queue system and cache use signed/encrypted serialization — these are safe. Focus on custom code.
Frequently Asked Questions
Is Laravel's queue serialization vulnerable?
No. Laravel encrypts and signs serialized queue payloads using your APP_KEY. Attackers cannot modify the serialized data without the key. However, if your APP_KEY is compromised, queue payloads become a potential attack vector.
What about serialize() — is that dangerous too?
serialize() itself is not dangerous — it just converts data to a string. The danger is on the deserialization side with unserialize(). However, if you serialize data that will later be deserialized from an untrusted source, the full chain is vulnerable.
Related Guides
Laravel Dangerous Function Calls: How to Eliminate eval, shell_exec, and system from Your Codebase
Functions like eval(), shell_exec(), system(), and proc_open() execute arbitrary code. If reachable from user input, they give attackers full server access.
Laravel APP_KEY Security: How to Generate, Rotate, and Protect Your Encryption Key
A missing, short, or committed APP_KEY compromises session encryption, signed URLs, and all data encrypted with Crypt. Generate a strong key and keep it out of Git.
How to Prevent SQL Injection in Laravel
SQL injection vulnerabilities in raw queries and improper Eloquent usage can expose your database. Learn how to write secure queries.
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