Question presented to candidate: "What does pickle do in Python, when would you use it, and why do people say you should never unpickle data you did not create yourself?"
What a strong answer should cover:
pickle.dumps/pickle.loads(anddump/loadwith binary files) turn almost any Python object graph into bytes and back, keeping types, shared references and cycles- Classes and functions are stored by reference (module and name), not by code, so the same class must be importable when loading; lambdas and local functions cannot be pickled
- The risk: unpickling runs the
REDUCEinstruction, which calls whatever callable the stream names (via__reduce__), sopickle.loadson untrusted bytes is arbitrary code execution - Mitigations: do not unpickle untrusted data; sign with HMAC to detect tampering; a restricted
Unpickler.find_classallowlist; prefer JSON or another data-only format across trust boundaries - Other limits: Python-only, not human-readable, fragile across code and version changes; protocols (default 4 on Python 3.8 to 3.13, 5 from 3.14)
- Where it is used:
multiprocessing, caching,copy-like deep clones, saving ML models (which is why loading a downloaded model file is a security decision)
Clarifying questions expected:
- Where does the pickled data come from, and who could have modified it?
- Does another language or a future version of the code need to read it?
Code / implementation expected: Optional β a round trip, and ideally a harmless __reduce__ demo of code running on load.