Stop 05 · Vulnerabilities & OWASP Top 10Topics · 7/11

Insecure Deserialization

Part of the Cybersecurity Roadmap

In short

Some data formats can rebuild whole objects, not just plain values. If your server rebuilds whatever a user sends, the user decides what your server creates. Keep incoming data boring.

Exploiting an application's process of converting serialized data back into objects — attackers can craft malicious serialized data leading to remote code execution in vulnerable systems.

The blob holds an Allen key as a wooden chair from an open flat-pack box builds itself into a jumbled shape with screws flying.

Think of it like this

The flat-pack box with its own instructions

You ordered a chair. The box arrives with instructions inside, and you follow them blindly. Someone swapped the sheet, and now you've built something you never ordered. Safe deserialization means you use your own instructions and only accept the parts you expect.

Watch it happen

Turning bytes into data, safely

Raw bytes
JSON.parse
Schema
Plain data
Use it

1/5A cart arrives from the client. Treat it as untrusted bytes, no matter who sent it.

The big ideas

What you need to know

What serialization is

Turning an object into bytes to store or send, then rebuilding it later. Rebuilding is the risky part.

Native formats rebuild types

Java serialization, Python pickle and PHP unserialize can recreate arbitrary object types. Never feed them untrusted input.

Prefer plain formats

JSON with a schema check carries data only. That's the safe default for anything from a user.

Sign what you hand out

If clients must hold data, like a cookie, sign it with an HMAC so tampering is detected.

See it in code

Walk through the code

ts
1import { z } from "zod";2 3const Cart = z.object({4  items: z.array(z.object({5    sku: z.string().max(40),6    qty: z.number().int().min(1).max(20),7  })).max(50),8});9 10app.post("/cart", express.json({ limit: "10kb" }), (req, res) => {11  const parsed = Cart.safeParse(req.body);12  if (!parsed.success) return res.status(400).json({ error: "Bad cart" });13  saveCart(req.session.userId, parsed.data);14  res.sendStatus(204);15});

1/4The schema lists exactly what a cart may contain, with types and size limits.

Zod strips unknown keys by default, so extra fields never reach your code. In Python, prefer json over pickle for anything from outside.

Save yourself the pain

Common mistakes

Oops

Loading a pickle or Java-serialized object from a cookie or upload "because it's convenient".

Do this instead

Use JSON plus a schema for anything crossing a trust boundary. Keep native formats for trusted internal storage.

Oops

Trusting data because it was base64 encoded.

Do this instead

Base64 is just encoding, not protection. Anyone can decode and change it. Sign it or keep it on the server.

Your mission

Add a schema guard

~30 min

Quick check

Your Python app loads user-uploaded settings files with pickle.loads. What's the safest fix?

Go deeper

  1. 1Read a conceptual explanation of how insecure deserialization can lead to code execution.
  2. 2Learn why this vulnerability is language and framework-specific in its exact exploitation technique.
  3. 3Understand the general defense: avoid deserializing untrusted data, or use safe serialization formats.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge