Your API accepts a session token in a cookie, decodes it, and reconstructs a user object on the server. An attacker modifies that token to include a malicious object. The server deserializes the payload, executes arbitrary code, and the attacker now controls the entire backend.
Insecure deserialization is one of the most dangerous deserialization attacks because it turns routine data handling into a pathway for Remote Code Execution (RCE). The Open Web Application Security Project (OWASP) originally listed insecure deserialization as #8 in the 2017 Top 10, and the 2021 update merged it into "Software and Data Integrity Failures." In the API context, deserialization of untrusted data maps to API8:2023 (Security Misconfiguration) and API10:2023 (Unsafe Consumption of APIs). For a full breakdown, see our guide to the 2023 OWASP API Top 10.
The Salt Labs State of API Security Report found that 95% of organizations experienced API security problems. Deserialization flaws are particularly dangerous because APIs process serialized data at a massive scale, often from untrusted sources.
What Is Insecure Deserialization?
Serialization converts an in-memory object into a format that can be stored or transmitted, such as a byte stream, JSON, XML, or a binary format. Deserialization is the reverse, reconstructing the object from that data.
A deserialization vulnerability occurs when an API deserializes data from an untrusted source without validation. The server assumes incoming serialized data is safe, when an attacker can modify it to inject malicious objects.
Here is what makes insecure deserialization dangerous:
- Code executes during reconstruction. Many languages run methods automatically during deserialization (constructors, finalizers, hooks). Attackers who control serialized input trigger arbitrary code before the application inspects the result.
- Type confusion is possible. Attackers can replace the expected object class with a different one. Any class available in the runtime can be instantiated, regardless of what the API expects.
- Validation after deserialization is too late. Checking the object after reconstruction is ineffective because malicious code already run during the deserialization process.
Why APIs Are Prime Targets for Deserialization Attacks
APIs expand the deserialization attack surface far beyond cookies and form fields. Understanding unsafe API consumption risks explains why:
- API request bodies. Java APIs using ObjectInputStream, Python APIs using pickle, and PHP APIs using unserialize() all process client-supplied serialized objects directly in request payloads.
- Session tokens and JWT payloads. APIs that store serialized objects in session tokens or JWT claims create a direct injection point. Attackers decode base64-encoded tokens, modify the serialized object, and send the altered token back.
- Webhook and event payloads. Microservices consume data from message queues and webhooks. Serialized objects from external systems get deserialized without validation, opening a pathway for attacks from third-party sources.
- Third-party API responses. APIs consuming responses from external services and deserializing without integrity checks are vulnerable. A compromised partner API can deliver malicious payloads that the consuming service executes blindly.
Pairing deserialization-safe coding with REST API security best practices provides a stronger foundation against these attack vectors.
How Gadget Chains Enable Remote Code Execution
A gadget is any class in the application's runtime that performs operations during deserialization. On its own, a gadget may be harmless. A gadget chain links multiple classes so that deserializing one object triggers a sequence of method calls that ultimately executes an attacker-controlled command.
Here is how a gadget chain works in a Java API:
- The attacker crafts a serialized object using a known gadget class from a library on the server's classpath (e.g., Apache Commons Collections).
- The API's ObjectInputStream.readObject() reconstructs the object.
- During reconstruction, the gadget's methods fire automatically, calling into the next gadget.
- The final gadget invokes Runtime.getRuntime().exec(), executing the attacker's command.
Gadget classes do not need to be used by the application. A single unused dependency pulled transitively through a library can provide the chain attackers need.
Real-World API Deserialization Vulnerabilities
Insecure deserialization has been at the center of some of the most damaging attacks in recent years. Here are verified incidents where deserialization flaws led to mass exploitation:
- CVE-2023-34362 (MOVEit Transfer). Attackers exploited a SQL injection in MOVEit's file transfer API to obtain a sysadmin API token, then triggered a .NET BinaryFormatter.Deserialize() call through the /api/v1/folders endpoint. The deserialization executed arbitrary code with administrator privileges. The CL0P ransomware group exploited the flaw as a zero-day, exfiltrating data from over 2,500 organizations.
- CVE-2017-9805 (Apache Struts REST Plugin). The Struts REST plugin deserialized XML payloads in API requests using XStreamHandler without restricting allowed types. Attackers sent crafted XML to REST endpoints, achieving RCE on any server running the plugin. The Equifax breach, exposing 147 million records, was attributed to an unpatched Struts vulnerability in the same timeframe.
- CVE-2015-4852 (Oracle WebLogic Server). WebLogic's T3 protocol deserialized Java objects from network requests without validation. Attackers used gadget chains from Apache Commons Collections for RCE on any exposed instance. The vulnerability was widely exploited for years after disclosure.
How to Detect Deserialization Vulnerabilities in APIs
Standard scanners rarely detect deserialization flaws because exploitation requires language-specific payloads targeting the server's library stack.
Our API security checklist covers the full workflow, but here are key methods:
- Identify deserialization entry points. Map every endpoint accepting binary data, base64-encoded strings, or serialization formats. Content-Type headers like application/x-java-serialized-object are strong indicators. Cookies, request bodies, and headers can all carry serialized objects.
- Test with known gadget chain payloads. Use tools like ysoserial (Java), ysoserial.net (.NET), or PHPGGC (PHP) to generate payloads targeting common libraries. Monitor for out-of-band callbacks or server behavior changes that confirm execution.
- Review code for unsafe functions. Flag any use of ObjectInputStream.readObject(), pickle.load(), unserialize(), or BinaryFormatter.Deserialize() that processes untrusted input. Any path from user data to these functions without type restriction is a confirmed vulnerability.
- Automated API security testing. Purpose-built API security testing platforms generate language-specific deserialization payloads and test every endpoint, covering attack vectors that generic DAST scanners miss.
How to Prevent Insecure Deserialization in APIs
The OWASP deserialization cheat sheet recommends avoiding deserialization of untrusted data entirely. When that is not possible, layered defenses reduce risk. Pair these strategies with API authentication best practices:
Never deserialize untrusted data
Eliminate native deserialization from API endpoints entirely. Use data-only formats like JSON with strict schema validation instead of language-native serialization. JSON represents key-value pairs and arrays only, so it cannot carry executable code or trigger method calls during parsing. Replacing ObjectInputStream (Java), pickle (Python), or unserialize() (PHP) with JSON removes the attack vector at its source.
- Define a JSON schema matching the expected input structure
- Replace deserialization endpoints with a JSON parser that validates against the schema
- Reject any request with Content-Type headers indicating native serialization formats
Restrict allowed types during deserialization
When native deserialization is unavoidable in legacy systems or internal communication, enforce a strict allowlist of permitted classes. The allowlist should include only the exact types the endpoint expects, rejecting everything else before reconstruction begins.
In Java, use ObjectInputFilter (introduced in Java 9, enhanced in Java 17):
java
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
"com.myapp.model.*;!*."
);
ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(filter);
The pattern com.myapp.model.*;!* allows only classes from the application's model package and blocks everything else. Without an allowlist, the deserializer accepts any class on the classpath, including gadget classes that enable RCE. For .NET APIs, avoid BinaryFormatter entirely and use System.Text.Json. In Python, replace pickle.load() with json.loads() for any endpoint accepting external input.
Sign and verify serialized data.
When APIs must exchange serialized objects between trusted microservices, apply digital signatures or HMAC (Hash-based Message Authentication Code) verification. The sending service computes an HMAC using a shared secret, attaches it to the payload, and the receiving service recomputes and compares it before proceeding. Always verify the signature before deserializing, never after, because malicious code executes during reconstruction.
Minimize the dependency footprint.
Gadget chains rely on third-party library classes. A single unused library can provide the chain an attacker needs for full RCE.
- Audit dependencies with OWASP Dependency-Check or Snyk to identify libraries with known gadget classes
- Remove unused libraries, particularly Apache Commons Collections (pre-4.1) and older Jackson versions, with enableDefaultTyping enabled.
- Run Software Composition Analysis (SCA) on every build to flag newly added dependencies that expand the attack surface
Integrate continuous API security testing in CI/CD.
Deserialization vulnerabilities resurface whenever a new dependency is added, or a developer reintroduces native serialization during a refactor. Running automated API security testing in a Continuous Integration/Continuous Deployment (CI/CD) pipeline catches unsafe patterns before production. Automated platforms detect endpoints accepting serialized data, generate language-specific payloads, and verify whether the server processes them unsafely with every build.
Secure Your APIs Before Attackers Exploit the Trust
Insecure deserialization turns routine data handling into a pathway for full server compromise. Eliminating native deserialization, enforcing type allowlists, and continuous testing close those gaps.
APIsec tests every endpoint for OWASP API Top 10 vulnerabilities, including deserialization flaws and unsafe data consumption.
Start a free scan and uncover what your current tools miss.
FAQs
What is insecure deserialization in simple terms?
Insecure deserialization occurs when an API reconstructs an object from untrusted data without validating its contents. Attackers modify the serialized data to include malicious code that executes during the reconstruction process.
How does OWASP classify insecure deserialization?
OWASP listed insecure deserialization as #8 in the 2017 Top 10, then merged it into "Software and Data Integrity Failures" (A08:2021). In the API Security Top 10, related risks appear under API8:2023 and API10:2023.
What is a gadget chain?
A gadget chain is a sequence of existing classes that an attacker links through deserialization. Each class triggers the next until the final one executes a system command, achieving RCE without injecting new code.
Can JSON APIs be vulnerable to deserialization attacks?
Pure JSON parsing is safe because JSON represents data only. However, APIs using JSON libraries configured to deserialize arbitrary types (such as Jackson with enableDefaultTyping) can still be exploited.
What are the most common deserialization attacks against APIs?
RCE through gadget chains is the highest-impact attack. Other deserialization attacks include Denial of Service (objects consuming excessive memory), privilege escalation (modifying session data), and authentication bypass (tampering with serialized tokens).

.webp)

