The API Guys
CWE-502 Deserialization of Untrusted Data warning banner with PHP code snippet showing unsafe unserialize usage
·5 min read·The API Guys

CWE-502 - The PHP Deserialization Flaw You Should Know About

SecurityPHPLaravelQuick BytesVulnerabilitiesWeb Development

If you write PHP for a living, there is a single function call that should make you pause every time you see it: unserialize(). When used carelessly, it is one of the most reliable ways for an attacker to achieve remote code execution on your server. The underlying weakness has a name - CWE-502: Deserialization of Untrusted Data - and it has been climbing the security charts for years.

This is a quick explainer on what it is, why PHP developers in particular need to care, and the practical steps you can take to keep it out of your codebase.

What is CWE-502?

CWE-502 describes a weakness where an application converts serialised data back into objects without properly validating or restricting what that data contains. Serialisation itself is harmless - it is simply the process of turning an in-memory object into a storable string. The danger comes when you deserialise data from an untrusted source, because the deserialisation process can trigger code execution.

In PHP, the serialize() function converts an object into a string representation. The unserialize() function does the reverse. The problem is that when PHP reconstructs an object during deserialisation, it automatically calls magic methods like __wakeup(), __destruct(), and __toString(). If an attacker can control the serialised string, they can craft a payload that chains these magic methods together to execute arbitrary code. Security researchers call these chains "gadget chains", and tools like PHPGGC exist specifically to generate them for popular PHP frameworks and libraries.

Why PHP is particularly exposed

PHP's native serialisation format is powerful but inherently risky. Unlike JSON, which only represents data, PHP's serialised format preserves full object types and class information. When you call unserialize(), PHP will attempt to instantiate whatever classes are described in the serialised string - and if those classes have exploitable magic methods, the attacker wins.

This is not helped by the fact that many PHP applications include large dependency trees through Composer. Even if your own code is clean, a single package with a vulnerable class can provide the gadget chain an attacker needs. The more packages you have installed, the larger your attack surface becomes.

CWE-502 sits within the OWASP Top 10 under "A08: Software and Data Integrity Failures" and has featured in the CWE Top 25 Most Dangerous Software Weaknesses for several consecutive years. It is not a niche concern.

Real-world examples in 2025

This is not an abstract problem. Throughout 2025, CWE-502 has appeared in critical vulnerabilities across the PHP ecosystem. WordPress plugins have been hit repeatedly, with multiple deserialization flaws disclosed in popular plugins like Everest Forms Pro and WP Easy Contact. The Roundcube webmail platform was affected by CVE-2025-49113, a CVSS 9.9 critical vulnerability that allowed post-authentication remote code execution through unsafe PHP object deserialization - and exploitation evidence appeared on underground forums within 48 hours of disclosure.

Laravel itself is not immune. The framework has had historical deserialization vulnerabilities, including CVE-2019-9081 in the Illuminate component. More recently, the research around leaked APP_KEYs demonstrated how deserialization chains in Laravel can be exploited when encryption keys are compromised - turning a leaked environment variable into full remote code execution.

What to do about it

The good news is that CWE-502 is entirely preventable with disciplined coding practices. Here are the steps every PHP developer should follow.

Avoid unserialize() on untrusted input. This is the most important rule. If you are accepting data from users, cookies, request parameters, message queues, or any external source, do not pass it through unserialize(). Use json_decode() instead. JSON only represents data structures - it cannot trigger object instantiation or magic method execution.

Use the allowed_classes parameter. If you absolutely must use unserialize(), PHP provides an allowed_classes option that restricts which classes can be instantiated during deserialization. Passing ['allowed_classes' => false] prevents any objects from being created, while passing a specific array of class names creates a strict allowlist. This is the minimum safeguard if serialisation cannot be avoided.

Audit your dependencies. Run composer audit regularly. Many deserialization vulnerabilities exist not in your own code but in third-party packages. Keeping dependencies up to date is one of the most effective defences - we have written about this at length in our guide to building a patching schedule.

Use static analysis. Tools like PHPStan, Psalm, and Snyk can detect calls to unserialize() and flag them for review. Integrating these into your CI/CD pipeline means unsafe patterns are caught before they reach production.

Secure your infrastructure. Some deserialization attacks rely on access to internal services like Redis or message queues. Ensure these are properly authenticated and not exposed to untrusted networks. Network segmentation and strong access controls add meaningful defence in depth.

The bottom line

CWE-502 is one of those vulnerabilities that feels like it should not still be a problem in 2025 - yet it keeps appearing in critical advisories because the patterns that enable it are so easy to introduce and so easy to overlook. A single unserialize() call on the wrong input can undo every other security measure you have in place.

The fix is straightforward: prefer JSON over PHP serialisation for data exchange, restrict unserialize() with allowed_classes when you cannot avoid it, keep your dependencies current, and use automated tooling to catch what code review might miss.

If you are unsure whether your application is exposed, get in touch. We regularly audit Laravel applications for exactly these kinds of issues.

Ready to Start Your Project?

Get in touch with our Leeds-based team to discuss your Laravel or API development needs.