Introduction
When PTC’s Windchill software was hit by a CVSS 9.3 critical vulnerability in June 2026 — one actively exploited to plant webshells on manufacturing and engineering systems — the root cause was not a novel attack technique. It was insecure deserialization. The same class of vulnerability that hit Apache Struts, Oracle WebLogic, and Java-based enterprise software for over a decade.
Insecure deserialization is one of those vulnerabilities that sounds obscure until you understand how it works. Once you do, you realize it is not obscure at all — it is a structural risk built into how most applications handle data moving between systems.
This guide explains what insecure deserialization is, how attackers exploit it, why it affects so many languages and frameworks, and what you can do to prevent it in your own systems.
What Is Insecure Deserialization?
To understand insecure deserialization, you first need to understand what serialization is.
Serialization is the process of converting an in-memory object — a class instance with fields, methods, and state — into a flat format like a byte stream, JSON string, or XML document so it can be stored or transmitted. A web application might serialize a session object and store it in a cookie. A distributed system might serialize a message and send it across a queue. A caching layer might serialize database results to disk.
Deserialization is the reverse: taking that flat representation and reconstructing a live object in memory.
The problem is what happens when an application deserializes data that came from somewhere it should not trust — a cookie, a URL parameter, an uploaded file, an API request, a message queue, or any channel an attacker can write to.
If the application blindly rebuilds whatever object the data describes, an attacker who controls that data can describe a malicious object. When the application deserializes it, the malicious logic runs.
This is insecure deserialization: trusting the contents of serialized data without verifying its integrity, origin, or safety before reconstructing it.
OWASP classified it in the Top 10 under A08 (Software and Data Integrity Failures) precisely because the vulnerability is not in one library or one language — it is a design pattern problem that recurs anywhere serialization meets untrusted input.

Why Does It Matter?
The consequences of insecure deserialization range from minor to catastrophic depending on what the deserialized code is allowed to do.
Remote Code Execution (RCE) is the worst outcome. An attacker crafts a serialized object that, when reconstructed, triggers a method call that executes arbitrary commands on the server. This is what CVE-2026-12569 in PTC Windchill allows: unauthenticated attackers send crafted serialized data to the Windchill endpoint, the server deserializes it, and the attacker gets a persistent webshell — full command execution, file access, lateral movement.
Beyond RCE, insecure deserialization can enable:
- Privilege escalation: an attacker deserializes an object with elevated permissions the server then acts on
- Denial of service: crafted objects trigger infinite loops or memory exhaustion during reconstruction
- Data tampering: a serialized session token is modified to change user identity or permissions
- Replay attacks: captured serialized messages are replayed to trigger repeated state changes
The reason it gets a CVSS 9.x score when combined with network accessibility is that exploitation often requires no authentication — you just need to reach the vulnerable endpoint.
Why Now?
Insecure deserialization is not new. What has changed is the attack surface.
Modern architectures distribute more serialized data across more channels than ever before. Microservices pass serialized messages between services. Session data travels in cookies. Caches serialize objects to Redis. Message queues carry serialized payloads between workers. Mobile apps send serialized state to APIs.
Each of these channels is a potential deserialization point. As organizations add more services and integrations, the number of places where serialized data crosses a trust boundary grows. Most of these boundaries are invisible to security teams that were not thinking about deserialization when the architecture was designed.
At the same time, tooling to exploit deserialization has matured significantly. Tools like ysoserial (Java gadget chain generation), PHPGGC (PHP gadget chains), and pickletools (Python) have lowered the skill floor for exploitation. An attacker no longer needs to understand the internals of the target application to craft a working payload — they need to know which library the application uses and pick the right gadget chain.
How Insecure Deserialization Works
The mechanics depend on the language. The pattern is the same: a crafted object is deserialized, and built-in methods that run automatically during reconstruction are hijacked to execute attacker-controlled code.
Java: Gadget Chains
Java’s native serialization format uses ObjectInputStream.readObject() to deserialize byte streams. The vulnerability is in how Java calls “magic methods” — specifically readObject(), readResolve(), and finalize() — on objects automatically during deserialization.
An attacker does not need a vulnerability in the application code itself. They need a class on the server’s classpath that has a dangerous readObject() implementation — a “gadget.” If they can chain multiple gadgets together so that one gadget calls another and eventually reaches an exec() or reflection-based invocation, they have remote code execution.
Apache Commons Collections was the library that made this widely known. Its InvokerTransformer class could be chained to invoke arbitrary methods on arbitrary objects. If Commons Collections was on the classpath — and it was in almost every Java enterprise application of that era — exploitation was straightforward.
The input: a serialized byte stream, delivered over the network. The server: readObject() is called, gadget chain executes, shell command runs. The application: completely unaware.
PHP: Magic Methods
PHP’s unserialize() function triggers __wakeup() and __destruct() on deserialized objects. If a class in the application defines a dangerous __destruct() — for example, one that deletes files, writes to disk, or executes code based on object properties — an attacker can inject a crafted serialized string through a cookie or POST parameter to trigger it.
Python: Pickle
Python’s pickle module can serialize and deserialize arbitrary Python objects, including lambdas and class instances. The __reduce__ method on a pickled object can specify a callable and arguments to run on deserialization — including os.system(). Any endpoint that unpickles user-provided data without restriction is trivially exploitable.
The Python documentation says this explicitly: “The pickle module is not secure. Only unpickle data you trust.”
.NET
The BinaryFormatter class in .NET had similar properties to Java’s native serialization. Microsoft deprecated it in .NET 5 and removed it in .NET 9 specifically because it was not safely usable with untrusted data. Legacy .NET applications that still use it are at risk.

Architecture: Where the Risk Enters
Understanding where serialized data enters your system helps locate the risk.
| Entry Point | Common Use | Risk |
|---|---|---|
| HTTP cookies | Session state, user preferences | High — attacker controls cookie |
| HTTP body (POST/PUT) | API payloads, file uploads | High — attacker controls body |
| URL parameters | State, tokens | Medium — visible, modifiable |
| Message queues | Inter-service communication | Medium — attacker may compromise a producer |
| Caches (Redis, Memcached) | Serialized object storage | Medium — depends on cache access controls |
| Uploaded files | Documents, images | High — attacker provides the file |
| WebSockets | Real-time data streams | High — bidirectional attacker input |
Every trust boundary where serialized data comes from outside your application code is a potential deserialization risk. The more trust boundaries, the larger the attack surface.
Real World Use Cases
1. Enterprise Manufacturing Software (CVE-2026-12569)
PTC Windchill PDMLink, used in aerospace and manufacturing for product lifecycle management, accepts a serialized data object from the network and reconstructs it without checking whether it is safe. Attackers exploited this to deploy persistent webshells on Windchill servers at government contractors and industrial firms. The federal remediation deadline was June 28, 2026.
2. Java Enterprise Applications
Multiple Java application servers — including Oracle WebLogic, IBM WebSphere, and JBoss — have had critical deserialization vulnerabilities related to Apache Commons Collections and similar libraries. In each case, an unauthenticated request containing a crafted serialized payload produced remote code execution on the application server.
3. PHP Content Management Systems
Several PHP frameworks have had unserialize() vulnerabilities triggered through crafted cookie values or POST parameters. An attacker who can inject a serialized string into an endpoint that calls unserialize() on user data can trigger destructors in loaded classes, leading to file writes or code execution.
4. Python Machine Learning Pipelines
ML pipelines that accept user-uploaded models in pickle format are particularly vulnerable. A maliciously crafted .pkl file will execute arbitrary code when loaded with pickle.load(). This is a real risk in platforms that allow users to upload custom model weights.
5. Microservice Message Queues
In event-driven architectures, services publish and consume serialized messages on queues. If a downstream service deserializes messages without validating the producer, a compromised upstream service — or a direct write to the queue — can inject malicious objects that execute in the consumer’s context.
Benefits of Getting This Right
Addressing insecure deserialization properly provides:
- Elimination of an entire class of RCE vectors — not a patch but a structural fix
- Reduced attack surface across all consumers of serialized data — fixing the pattern rather than individual occurrences
- Compliance improvement — OWASP Top 10 and security frameworks like SOC 2 and ISO 27001 reference this class of vulnerability
- Defense in depth — even if an attacker finds another way in, they cannot escalate through deserialization
Limitations and What This Fix Does Not Cover
Mitigating insecure deserialization does not protect against:
- Injection attacks — SQL injection, command injection, and XSS are separate vulnerability classes
- Authentication weaknesses — once an attacker is authenticated, different controls apply
- Library vulnerabilities in safe formats — XML parsers have their own issues (XXE); JSON parsers have prototype pollution risks in JavaScript
Serialization format safety is also not binary. JSON is generally safer than Java’s native format, but parsing untrusted JSON can still cause denial of service or injection depending on the parser and how the data is used.
Engineering Tradeoffs
Switching from native serialization to a safer format is not free.
What improves: the attack surface for object injection drops significantly when you use a format that cannot encode arbitrary object types.
What becomes harder: if your codebase relies on native serialization for performance (binary formats are compact and fast) or for complex object graphs (polymorphism, circular references), migrating to JSON or Protocol Buffers requires significant refactoring.
New complexity introduced: allowlist-based deserialization (only permitting known safe classes) requires maintaining the allowlist over time. Cryptographic signing of serialized data adds key management overhead.
When not to use native serialization: never use Java ObjectInputStream, PHP unserialize(), Python pickle, or .NET BinaryFormatter on data you do not completely control. If you need to accept serialized data from users, external systems, or any channel you do not own end-to-end, use a data format without object instantiation semantics.
Best Practices
1. Never deserialize untrusted data using native serialization formats. If data crosses a trust boundary — user input, third-party API, uploaded file — do not use Java ObjectInputStream, PHP unserialize, Python pickle, or .NET BinaryFormatter on it.
2. Use data-only formats for untrusted input. JSON, XML with schema validation, and Protocol Buffers do not instantiate arbitrary objects during parsing. They are significantly safer for deserializing untrusted data.
3. Implement cryptographic integrity checks. Sign serialized data with HMAC or similar before storing or transmitting it. Verify the signature before deserializing. An attacker cannot modify signed data without detection.
4. Apply class allowlists when native deserialization is unavoidable. Some frameworks support configuring ObjectInputStream to reject classes not on a predefined allowlist. This blocks gadget chain exploitation by preventing unknown classes from loading.
5. Run deserialization in a sandboxed environment. If deserialization must happen on untrusted input (for example, a plugin loader), do it in an isolated process with minimal permissions. Contain the blast radius.
6. Keep libraries updated. Gadget chains rely on specific library versions. Keeping Commons Collections, Spring, and other common libraries patched eliminates known gadget chains.
7. Monitor for deserialization anomalies. Log deserialization errors and unexpected class names. Exploitation attempts often produce exceptions when a gadget chain fails. These errors are usually ignored — they should not be.
Common Mistakes
Assuming a format is safe because it is not Java binary. PHP unserialize() and Python pickle carry the same object instantiation risks as Java’s native format. The format name does not determine safety — the semantics do.
Patching libraries without fixing the architecture. Patching Apache Commons Collections removes one gadget chain. It does not fix the underlying pattern of deserializing untrusted data. A new gadget chain in a different library can re-exploit the same entry point.
Treating HMAC as encryption. Signing serialized data prevents tampering but does not encrypt it. If the serialized data contains sensitive information, it still needs to be encrypted. HMAC and encryption solve different problems.
Testing only the happy path. Functional testing does not catch deserialization vulnerabilities. Penetration testing and static analysis tools (like Find Security Bugs for Java) are needed to surface deserialization sinks and unsafe patterns.
What Most People Get Wrong
“This only affects old Java applications.” Insecure deserialization affects Python, PHP, .NET, and Ruby as well. Python pickle is particularly dangerous in ML pipelines, where it is the default serialization format for model files. Any language that supports reconstructing objects from stored data has some form of this risk.
“JSON is completely safe to deserialize.” JSON does not instantiate arbitrary objects during parsing, which is why it is safer than Java’s native format. However, some JSON parsers in JavaScript can be exploited for prototype pollution. The risk is lower, not zero.
“CISA KEV means only government systems are at risk.” CISA adds vulnerabilities to the KEV catalog based on active exploitation evidence, not victim type. A CVE on the KEV list means it is being used in active attacks against real targets. Government agencies are required to patch it — everyone else should treat it as an urgent signal.
Future Outlook
The deserialization risk is not going away. As systems exchange more data across more channels, the number of deserialization points grows. The shift to AI-assisted code generation may actually make this worse: code generators that suggest pickle.load() or unserialize() without security context will produce vulnerable code that developers may not recognize as dangerous.
The trend in language ecosystems is toward safer defaults. .NET removed BinaryFormatter. Python 3.12 added deprecation warnings for some pickle usage patterns. Java has added deserialization filters (ObjectInputFilter) but has not removed unsafe behavior.
The practical trajectory for most organizations is: migrate legacy code away from native deserialization formats, enforce code review policies that flag deserialization sinks, and run automated scanning that detects unsafe patterns before they reach production.
FAQ
1. What is insecure deserialization? Insecure deserialization occurs when an application deserializes data from an untrusted source without validating its contents or integrity, allowing an attacker to inject malicious objects that execute code during reconstruction.
2. Which languages are affected by insecure deserialization? Java, PHP, Python, .NET, and Ruby all have native serialization mechanisms that are unsafe when used with untrusted input. The risk exists wherever an application reconstructs objects from external data.
3. What is a gadget chain? A gadget chain is a sequence of existing classes in an application’s classpath that, when instantiated in a specific order during deserialization, ultimately executes attacker-controlled code. The attacker does not need to inject new code — they reuse existing library code in an unintended sequence.
4. Is JSON deserialization safe? JSON is significantly safer than Java or PHP native serialization because it does not instantiate arbitrary objects during parsing. However, JavaScript JSON parsers can be vulnerable to prototype pollution, and some JSON libraries with type inference features reintroduce object instantiation risks.
5. What is the OWASP classification for insecure deserialization? OWASP classifies it under A08 — Software and Data Integrity Failures — in the OWASP Top 10. It was previously listed as A08:2017 — Insecure Deserialization as its own category.
6. How is CVE-2026-12569 related to insecure deserialization? CVE-2026-12569 in PTC Windchill is caused by insecure deserialization of untrusted data. The server accepts a serialized object from the network and reconstructs it without verification, allowing unauthenticated attackers to execute arbitrary code and deploy persistent webshells.
7. What is the difference between serialization and deserialization? Serialization converts an in-memory object to a storable or transmittable format (bytes, JSON, XML). Deserialization reverses this — it reads the stored format and reconstructs the object in memory. The vulnerability is in deserialization, not serialization.
8. How do I prevent insecure deserialization in Java? Do not use ObjectInputStream with untrusted data. If you must, use ObjectInputFilter to allowlist permitted classes. Sign serialized data with HMAC before storage or transmission. Prefer JSON or Protocol Buffers for external data exchange.
9. Why is Python pickle dangerous? Python’s pickle module allows a pickled object to specify a callable and arguments to execute upon deserialization via the __reduce__ method. This means any callable — including os.system() — can be triggered by unpickling a malicious .pkl file.
10. What should I do if my application is vulnerable to insecure deserialization? Identify all deserialization sinks in your codebase. Determine whether any accept externally controlled data. Prioritize migrating those to safe formats. As an interim measure, apply class allowlisting, add HMAC signing, and monitor deserialization errors as potential attack indicators.
Analyst Perspective
The pattern in enterprise software vulnerabilities over the past decade is consistent: the most damaging exploits are not in obscure edge cases — they are in foundational architecture decisions that made sense at the time and were never revisited.
Java’s native serialization was designed for performance and developer convenience within trusted environments. It was not designed to accept data from the internet. When distributed architectures emerged and serialized data started crossing network boundaries, the mechanism moved into a context it was never built for. No one changed the mechanism.
CVE-2026-12569 in PTC Windchill is not an anomaly. It is what happens when a serialization mechanism designed for trusted inter-process communication is exposed to an untrusted network. The specific vulnerability is new; the pattern is two decades old.
The more important signal is that CISA added it to KEV with a same-day federal deadline. That catalog now has clear market power: it forces prioritization, creates regulatory pressure, and increasingly shapes insurance and procurement requirements. A CVE on the KEV list is no longer just a security finding — it is a business risk event.
For developers building new systems: serialize only data you need to reconstruct, use formats that cannot encode object types (JSON, Protobuf), and treat deserialization of external input as an explicit architectural decision requiring security review — not a default behavior.
Key Takeaways
- Insecure deserialization occurs when an application reconstructs objects from untrusted data without verification, enabling attackers to inject malicious code that executes automatically
- The vulnerability affects Java, PHP, Python, .NET, and Ruby — any language with native object serialization
- In Java, attackers use “gadget chains” — sequences of existing library classes that produce code execution when deserialized in the right order
- Prevention requires eliminating native deserialization of untrusted data, not just patching libraries
- Use JSON, Protocol Buffers, or other data-only formats for any data crossing a trust boundary
- HMAC signing of serialized data prevents tampering even if the format is not perfectly safe
- CVE-2026-12569 (CVSS 9.3) confirms this class of vulnerability is still actively exploited in 2026
Continue Learning
- Squidbleed (CVE-2026-47729): What Developers Need to Know About the 29-Year-Old Squid Proxy Vulnerability
- libssh2 CVE-2026-55200: Critical RCE With No Official Patch — What Developers Must Do Now
- AI-Accelerated Cyberattacks: How Defenders Are Responding
- What is Model Context Protocol (MCP)?
About GAVIHOS
GAVIHOS helps developers, founders and technology enthusiasts understand AI, software engineering and emerging technologies through practical guides, tutorials and industry analysis.
Stay Updated
Follow GAVIHOS for practical AI, technology and developer-focused insights.