AppSec · Jun 30, 2026 · 7 min read

Insecure deserialization: a gadget chain needs proof, not a pattern flag

Detecting that an endpoint accepts serialized objects is reachability - confirming a gadget chain without running a real command is where severity is decided.

Deserialization bugs earn their critical rating because the dangerous work happens before type-checking finishes. A gadget chain does not need any application-specific code - it stitches together methods already sitting on the classpath, invoked as the object is reconstructed. Detecting that an endpoint accepts serialized input is reachability. Proving the chain assembles, without ever running a real command, is where the severity is actually decided.

01The logic runs before the type check

Safe code validates a value and then acts on it. A vulnerable deserializer acts while rebuilding the object graph - calling readObject, property setters and side-effecting constructors - and only afterward discovers it built something it should not have. By then the gadget has already fired. That inversion is why the class is critical rather than merely risky.

bytes in ──► reconstruct object graph gadget methods invoked here ──► type check (too late) safe path ──► parse to a known schema validate ──► then act (nothing runs early)
The vulnerable path executes gadget code during reconstruction; the safe path validates against a schema before anything runs.

02Confirm the chain, do not weaponize it

The oracle discipline is the same as everywhere else: prove capability, run nothing dangerous. Instead of a real command or a spawned subprocess, the confirming payload uses a benign out-of-band marker - a unique, attributable callback that fires only if the sink was reached. It demonstrates the chain assembled and executed a harmless lookup, not a shell. Out-of-band confirmation is off by default and used only with authorization.

benign-oast-probe.txtpayload
# gadget chain wired to a HARMLESS out-of-band lookup, not a command
sink: reflection gadget on the app's classpath
action: resolve ap-62615533.oast.probe   # unique, benign, attributable

# confirmation, entirely out of band:
callback log ──► DNS/HTTP hit for ap-62615533.oast.probe
# the chain assembled and reached execution. No shell, no file, no command.
Proven - CriticalDeserialization gadget chain reaches execution - /api/import
POST /api/import Content-Type: application/x-java-serialized-object ──► out-of-band callback fired for ap-62615533.oast.probe chain assembled from on-classpath gadgets; only a benign lookup was triggered
No command executed, no process spawned - a benign attributable callback only. Critical: a real payload at this sink is remote code execution.

03One fingerprint misses most of the surface

Java's magic bytes (0xAC 0xED 0x00 0x05) mark a standard serialized object, but that is one format among many. Jackson with default typing, Kryo, Python pickle, PHP serialize and Ruby Marshal each present a different fingerprint and a different sink, so a single-format detector reports clean on most real deployments.

FormatFingerprintTypical sink
Java native0xACED0005 magic bytesreadObject on the classpath
JacksonJSON with type hints / default typingPolymorphic type resolution
Python pickleOpcode stream (proto markers)__reduce__ during load
PHPO:len:"Class" serialize format__wakeup / __destruct
RubyMarshal version prefixObject reconstruction hooks

04Fix the deserializer, not the gadgets

Gadgets are never fully enumerable, so chasing individual chains is a losing game. The durable fix constrains the deserializer itself: Java 9+ serialization filters (JEP 290, ObjectInputFilter) allowlist expected types before a chain can assemble; Jackson should disable default typing and use explicit types; pickle and Marshal should not touch untrusted input at all.

5+
formats, five fingerprints
0
commands run to confirm
allowlist
the fix lives at the deserializer

Prove capability with a benign callback, rate it on the sink, and remediate at the one place that can actually hold the line - the type filter - not the endless list of gadgets downstream of it.

Evidence over heuristicsReachable beats foundMonitor → Block: rolling out a gate without slowing teamsIaC-grounded threat modelingAir-gapped AppSec with no phone-homeOne platform vs three tools
See it on your own app →