A format that restores objects must instantiate whatever classes the stream names, and the stream's author chooses them. Python's pickle, also behind joblib model files, is the clearest case:
import pickle, pickletools
class Order: # what an attacker uploads instead of an order
def __reduce__(self): # "rebuild me by calling print(...)": any callable works
return (print, ("code ran inside pickle.loads",))
payload = pickle.dumps(Order())
print([arg for _, arg, _ in pickletools.genops(payload) if isinstance(arg, str)])
print("loads returned:", pickle.loads(payload))Output
['builtins', 'print', 'code ran inside pickle.loads'] code ran inside pickle.loads loads returned: None
The stream says "import builtins.print and call it"; an attacker names os.system. Java serialization, unsafe YAML loaders and polymorphic JSON typing share this flaw (CWE-502). Schema'd formats decode only into declared types, yet libraries slip: CVE-2024-47561 (CVSS 9.3) let schema parsing in Avro 129 's Java SDK up to 1.11.3 run arbitrary code, and CVE-2025-30065 (CVSS 10.0) did the same in Parquet 129 's parquet-avro up to 1.15.0. Never unpickle untrusted data, and keep format libraries patched.