Developers prevent deserialisation attacks by avoiding untrusted data formats where possible and never deserialising data without strict type and schema controls. Use safe libraries, enable integrity checks, and reject unexpected classes, fields, or object graphs. Treat any deserialised input as hostile, and remove features such as dynamic object construction that expand attack surface.
Why deserialisation is dangerous in the first place
Deserialisation becomes risky when application code turns attacker-controlled bytes or text into live objects with methods, constructors, references, or side effects. At that point, the parser is no longer just reading data, it is helping the attacker influence program behaviour. That is why insecure deserialisation often leads to injection, object injection, or remote code execution when the runtime or library accepts unsafe object graphs.
Any language or framework that supports rich object deserialisation needs the same mental model: the input is not “data until proven otherwise”, it is executable structure until constrained. The safer the format and the smaller the allowed type surface, the less opportunity an attacker has to trigger unexpected behaviour during object reconstruction. For a broader view of where this fits in common web attack patterns, see the Web Application Attacks Guide.
Safe handling also means refusing convenience features that enlarge the attack surface, such as implicit polymorphism, dynamic class loading, or automatic object instantiation from untrusted input. If the application only needs simple data transfer, plain schema-bound structures are usually safer than full object serialisation.
Controls that actually reduce deserialisation exposure
The most effective control is to avoid deserialising untrusted data at all where a safer representation exists. When deserialisation is unavoidable, the application should enforce strict type allowlists, schema validation, and integrity checks before any object is materialised. That limits what can be created and makes malformed or malicious payloads fail early rather than continuing into business logic.
Library choice matters because some serializers and language runtimes are inherently harder to secure than others. Developers should prefer safe, modern libraries and configure them to reject unexpected classes, fields, polymorphic types, or nested object graphs. In practice, the line between “parser” and “runtime” matters: once the parser can select classes or invoke constructors from attacker input, the risk jumps sharply. The Insecure Deserialisation Guide goes deeper on object injection, gadget chains, and allowlist filtering.
Integrity controls are most useful when they are paired with narrow deserialisation rules. A signature or MAC can tell you the payload was not altered, but it does not make a dangerous object model safe by itself. If the trusted producer can still generate a harmful class graph, the application can remain exploitable even though the bytes are authentic.
What to do when deserialisation cannot be removed
When a legacy protocol or integration forces deserialisation, the practical goal is to reduce blast radius rather than assume the parser is safe. Keep the trusted type set minimal, disable dynamic object construction, and isolate the code path so that deserialised objects do not gain broad access to filesystem, network, or privileged application functions. That is especially important in services that process many external requests, because a single weakness can become a high-volume exploitation path.
Testing should focus on whether the application accepts unexpected classes, unexpected properties, or nested references that should not exist in normal traffic. A secure build should fail closed when input violates the expected schema, not try to coerce it into a useful shape. The developer question is not whether the payload “looks valid enough”, but whether the runtime ever gets a chance to create an object with attacker-chosen behaviour.
If the application uses a framework or data format with known unsafe defaults, document the compensating controls and verify them in code review and automated tests. This is where teams often overestimate library safety and underestimate configuration drift, especially after dependency upgrades or framework refactors.
Risk and Threat Considerations
Deserialisation flaws matter because they can turn a routine data-handling path into an execution path. An attacker who can control the payload may be able to reach gadget chains, trigger unsafe methods during object creation, or push malformed object graphs into sensitive logic. The risk rises when the application processes external input at scale or when the resulting objects can influence file access, command execution, authentication state, or downstream requests.
Failure mechanism: The parser accepts untrusted input, reconstructs objects with too much freedom, and activates code paths or side effects that were never meant to be reachable from external data.
Impact: The outcome can range from application crash and logic corruption to privilege abuse, data exposure, or remote code execution, depending on the runtime, library, and reachable object model.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP ASVS, CIS Controls v8 and NIST SP 800-53 Rev 5 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP ASVS | V2 — Validation and Business Logic | Deserialisation attacks rely on unsafe input handling and object construction rules. |
| V15 — Secure Coding and Architecture | Secure design should avoid unsafe object creation and minimise attack surface. | |
| Recommendation — Validate input strictly and reject unexpected structures before object creation. Remove dynamic object construction and prefer safer data representations. | ||
| CIS Controls v8 | CIS-16 — Application Software Security | Secure application coding and hardening directly reduce deserialisation exploitation paths. |
| Recommendation — Build secure coding checks into review, testing, and release gates. | ||
| NIST SP 800-53 Rev 5 | SI-10 — Information Input Validation | Deserialisation safety depends on rejecting malformed or unexpected input before processing. |
| SA-11 — Developer Testing and Evaluation | Testing must confirm unsafe deserialisation paths are blocked before deployment. | |
| Recommendation — Enforce strict validation on all deserialised input. Test deserialisation paths for unexpected types, fields, and object graphs. | ||
Practitioner Guidance
What to verify: Confirm that every deserialisation entry point has an explicit allowlist or schema boundary, and that polymorphic or reflective object creation is disabled unless there is a documented business need.
Common mistake: Teams often secure the transport layer and assume the payload is safe. A signed or encrypted message can still be dangerous if the object model itself is too permissive.
What good looks like: Unknown classes fail closed, unexpected fields are rejected, and the application can process only the minimum object types needed for the use case.
Practitioner takeaway: The safest deserialisation design is usually the smallest one, if untrusted input never becomes a rich object graph, the attacker loses the chance to turn parsing into code execution.
Related resources from NHI Mgmt Group
- How should Android developers prevent overlay attacks on screens that collect sensitive information?
- How do developers prevent reentrancy attacks?
- How should security teams prevent man-in-the-middle attacks on remote access?
- How should security teams prevent rainbow table attacks on password hashes?