pickle's reduce can call arbitrary callables during unpickling, giving RCE
pickle is a Python-specific serialization format that can represent almost any object, including classes and functions. During unpickling, pickle reconstructs objects by calling constructors and the reduce protocol. An attacker can craft a byte stream whose reduce returns a callable such as os.system and arguments to execute. When the victim unpickles that stream, the callable runs immediately, before any validation you might add afterwards. There is no safe mode and no way to inspect a pickle before loading it that is guaranteed to be safe, because the payload only needs to be valid enough to reach the callable. The practical rule is simple: never unpickle data from an untrusted source. Use json, msgpack, protobuf, or another data-only format, and validate with a schema. If you must transfer Python objects, restrict them to trusted systems with network controls and authentication, and sign or encrypt the payload.
Any callable reachable through reduce can be invoked during unpickling, not just os.system.
Signing the pickle does not make it safe to load untrusted data; it only proves who sent it.
Restricted unpicklers and find_class overrides are hardening measures, not guarantees.
Alternatives: json for data, msgpack for compact binary, protobuf or Avro for schemas, and dataclasses for reconstructing typed objects.
Common mistake: treating pickle as a general-purpose data format for caching or message queues that accept external input.
Common mistake: assuming that a pickle you generated earlier is safe because you wrote it; if the storage or network is compromised, the payload can be replaced.
Version note: pickle protocol 5 (3.8+) added out-of-band buffers but did not change the security model. The risk is the same across all protocols.
0-2 years experience
2-5 years experience
5-8 years experience
8+ years experience