Pickle is Python's built-in, general-purpose object serialization module — usable for saving ML models, but carrying a genuinely serious security risk that every ML practitioner needs to understand before loading any pickle file.
Basic Usage
import pickle
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
with open("model.pkl", "wb") as f:
pickle.dump(model, f)
with open("model.pkl", "rb") as f:
loaded_model = pickle.load(f)
print(loaded_model.predict(X_test[:3]))
The Security Risk, Explained Precisely
Pickle doesn't just store data — it can store instructions for reconstructing arbitrary Python objects, including a special mechanism (the __reduce__ method) that lets an object specify a function to call during unpickling. A malicious actor can craft a pickle file whose "reconstruction instructions" happen to be a call to os.system() or similar — meaning simply loading the file (not even using the resulting object) can execute arbitrary code on your machine.
# Conceptual illustration of the attack (NOT something to actually run) --
# a malicious class can hijack __reduce__ to execute code on unpickling
class MaliciousPayload:
def __reduce__(self):
import os
return (os.system, ("echo THIS COULD BE ANY COMMAND AT ALL",))
# pickle.dump(MaliciousPayload(), open("looks_like_a_model.pkl", "wb"))
# pickle.load(open("looks_like_a_model.pkl", "rb")) -> silently runs the command
The resulting file looks, from the outside, exactly like a normal saved model — there's no way to tell it's malicious just by looking at the filename or extension.
The Practical Rule
| Situation | Safe to Unpickle? |
|---|---|
| A model you trained and saved yourself | Yes |
| A model from your team's verified, access-controlled internal storage | Yes |
| A model downloaded from an unfamiliar website, forum, or unverified public source | No — never |
| A model attached to an email or message from an unknown sender | No — never |
Safer Alternatives When Trust Is a Concern
# For simple models, safer formats avoid pickle's arbitrary-code-execution risk entirely
import json
import numpy as np
# ONNX -- an open, cross-platform format for many model types, without pickle's risk
# skops -- a scikit-learn-focused library specifically designed as a safer pickle alternative
import skops.io as sio
sio.dump(model, "model.skops")
loaded_model = sio.load("model.skops", trusted=True) # still requires explicit trust, but safer by design
Practical Use Cases
- Saving models within a trusted, controlled environment (your own project, your team's internal systems)
- General Python object serialization beyond just ML models
Common Mistakes
- Loading a pickle file from the internet without verifying its source, treating it the same as any harmless data file.
- Assuming a
.pklextension guarantees the file is "just data" — it can contain arbitrary reconstruction logic. - Not considering safer alternatives (ONNX, skops) when models genuinely need to be shared across trust boundaries.
Interview Relevance
Q: "Why is unpickling untrusted data considered a serious security vulnerability, not just bad practice?" Pickle allows objects to define custom reconstruction logic via __reduce__, which can call arbitrary functions (like os.system) during deserialization — simply loading a maliciously crafted pickle file can execute attacker-controlled code, with no visible warning sign in the file itself.
Practice Question
Your company wants to let external partners upload "custom models" to a shared platform for automatic loading. Explain why using pickle for this specific use case would be dangerous, and propose an alternative.