SaferPickle is a Python library that provides a safer alternative to
Python's pickle module. It is a heuristic-based system that uses a two-tiered
approach to scan pickle files for malicious content, minimizing latency in
trivially identifiable cases and providing high-confidence results in more
complex situations.
SaferPickle employs a two-tiered scanning approach:
- Picklemagic: A fast approach that detects suspicious module instantiations by safely loading the file using fake objects.
- Genops: This approach string-matches the opcodes from the pickle file against predefined lists of unsafe, suspicious, and safe strings to assess the potential for malicious intent.
You can install SaferPickle from PyPI:
pip install saferpickleAlternatively, please use requirements.txt to install dependencies.
Here are the different ways you can use SaferPickle:
You can use the security_scan function to scan a pickle file and get a report
of the findings.
import safer_pickle
import pickle
class MyObject:
def __init__(self, value):
self.value = value
my_object = MyObject("some data")
pickle_bytes = pickle.dumps(my_object)
scan_results = safer_pickle.security_scan(pickle_bytes)
if scan_results["unsafe"] > 0:
print("Unsafe content found!")
elif scan_results["suspicious"] > 0:
print("Suspicious content found!")
else:
print("Pickle file seems safe.")The security_scan function returns a dictionary containing scores for
unsafe, suspicious, and unknown finds.
You can use hook_pickle() to automatically and transparently add SaferPickle's
security scan to all the standard pickle-like libraries (pickle, _pickle,
cloudpickle, joblib, dill). This is the easiest way to protect your
application from unsafe pickles.
import safer_pickle
import pickle
safer_pickle.hook_pickle()
# Now, any call to pickle.load() or pickle.loads() will be protected.
# For example, if you try to load a malicious pickle file, it will raise
# a safer_pickle.UnsafePickleDetectedError.
try:
# malicious_pickle_bytes is a pickle file that contains malicious code
pickle.loads(malicious_pickle_bytes)
except safer_pickle.UnsafePickleDetectedError as e:
print(f"Blocked malicious pickle file: {e}")You can also use safer_pickle.load() and safer_pickle.loads() as direct
replacements for pickle.load() and pickle.loads(). These functions provide
more control over the security scan.
import safer_pickle
# This will raise a safer_pickle.UnsafePickleDetectedError if the pickle is unsafe
try:
obj = safer_pickle.loads(malicious_pickle_bytes)
except safer_pickle.UnsafePickleDetectedError as e:
print(f"Blocked malicious pickle file: {e}")
# You can also use a strict check, which is more aggressive in detecting
# potentially malicious content.
try:
obj = safer_pickle.loads(malicious_pickle_bytes, strict_check=True)
except safer_pickle.StrictCheckError as e:
print(f"Blocked by strict check: {e}")
# If you trust the source of the pickle file, you can bypass the security scan.
obj = safer_pickle.loads(pickle_bytes, allow_unsafe=True)SaferPickle also comes with a command-line tool for scanning pickle files.
safer_pickle_cli --directory=<dir_path_to_scan>This will recursively scan the specified directory and generate a JSON report with the classification for each file.
We welcome contributions! Please see our contributing guidelines in CONTRIBUTING.md for more information.
SaferPickle is licensed under the Apache 2.0 License. See the LICENSE file for more details.
This is not an officially supported Google product. This project is not eligible for the Google Open Source Software Vulnerability Rewards Program.