pysafe-pickle
A drop-in pickle replacement in Rust that never executes code on load, with schema migrations and zero-copy tensors.
581 downloads / 30 days · PyPI
pip install pysafe-picklepickle deserialization runs arbitrary code: __reduce__ and __setstate__ are called on load, which is why loading an untrusted pickle is equivalent to running an untrusted script. pysafe-pickle keeps the API and drops that behaviour.
It is a Rust core (PyO3 + maturin) behind the same dumps / loads / dump / load signatures, plus the Pickler / Unpickler streaming classes and PickleBuffer (PEP 574).
What it changes
- No arbitrary execution. Deserialization never calls
__reduce__or__setstate__. Only allowlisted types decode; anything else raisesUnsafeTypeError. The allowlist covers primitives,str/bytes, sequences, mappings, sets, and any@dataclass, and is narrowable per call. - Schema evolution. Tag a dataclass with
__pysafe_pickle_version__and register@psp.migrate(from_version=…, to_version=…)hooks. Migration chains (v1 → v2 → v3) resolve automatically, so old payloads keep loading after the model changes. - HMAC integrity. Pass
hmac_keytodumps/loadsand tampered data raisesHMACErrorinstead of decoding. - Zero-copy tensors. NumPy and PyTorch buffers round-trip without a copy.
Compatibility
v1.0.x shipped as pygraph. v1.1.0 renamed the import to pysafe_pickle and kept a shim: import pygraph still works (with a FutureWarning), and files written with the old PYGR magic still deserialize with zero warnings. New payloads use PSPK.