How to Load Pickle Files Safely in Python
This code demonstrates how to load pickle files safely in Python by using a restricted unpickler that only allows specific, trusted classes, preventing arbitrary code execution from untrusted pickles.
Python code
37 linesimport pickle
# Default pickle.load is unsafe: it executes arbitrary code when unpickling.
class Unsafe:
def __reduce__(self):
return (eval, ("open('/tmp/pickle_demo.txt', 'w').write('pwned')",))
# Create a malicious payload (simulating untrusted source)
malicious_data = pickle.dumps(Unsafe())
# Safe approach: use a restricted unpickler that only allows specific classes
class SafeUnpickler(pickle.Unpickler):
ALLOWED_GLOBALS = {"builtins": {"list", "dict", "set", "tuple", "int", "str", "bool", "NoneType"}}
def find_class(self, module, name):
if module in self.ALLOWED_GLOBALS and name in self.ALLOWED_GLOBALS[module]:
return super().find_class(module, name)
raise pickle.UnpicklingError(f"Blocked class: {module}.{name}")
# Demonstrate the attack vector (commented out for safety)
# pickle.loads(malicious_data) # This would write 'pwned' to /tmp
# Show safe loading with allowed classes
safe_data = pickle.dumps({"name": "Alice", "scores": [85, 92, 78]})
try:
result = SafeUnpickler(io.BytesIO(safe_data)).load()
print("Safe load result:", result)
except pickle.UnpicklingError as e:
print("Blocked:", e)
# Show that unsafe classes are rejected
try:
SafeUnpickler(io.BytesIO(malicious_data)).load()
except pickle.UnpicklingError as e:
print("Blocked malicious payload:", e)
import io
Output
Safe load result: {'name': 'Alice', 'scores': [85, 92, 78]}
Blocked malicious payload: Blocked class: __main__.Unsafe
How it works
The pickle module is document unsafe for untrusted data because it can execute arbitrary code during unpickling. The SafeUnpickler class overrides find_class, which is called for every class reference during unpickling, and only allows classes explicitly listed in ALLOWED_GLOBALS. This restricts what modules and names can be imported, blocking malicious payloads. The demo creates a malicious class that would write a file, but the safe unpickler rejects it before it can execute.
Common mistakes
- Using `pickle.load` or `pickle.loads` directly on untrusted data without any restriction.
- Forgetting to import `io` when working with `BytesIO` for pickled data.
- Making `ALLOWED_GLOBALS` too permissive, allowing modules like `os` or `subprocess`.
Variations
- Use `pickletools.optimize` to reduce pickle size for storage or transmission.
- Consider using `json` or `msgpack` instead of pickle for untrusted data, as they are safer formats.
Real-world use cases
- Loading cached model artifacts or preprocessed data in machine learning pipelines where the pickles come from trusted internal sources.
- Deserializing configuration objects or user session data in a web backend without executing untrusted code.
- Transferring complex Python objects between services where you control the producer and can enforce class restrictions.
Sponsored
More from Files & data
- Append a Line to a Log File in Python easy
- Audit File Permissions Across a Project in Python easy
- Automatically Detect Corrupted Files Using SHA-256 Checksums in Python easy
- Automatically Highlight Data Validation Errors Inside Excel Files in Python easy
- Build a Command-Line To-Do List Application with Data Persistence in Python easy
- Build a File Index by Relative Path Hash Map in Python easy
Keep learning
Related tutorials and quizzes for this topic.