Arbitrary Code Execution via Malicious Pickle-Serialized Models from Public Hubs
Overview
A persistent and critical vulnerability in the machine learning supply chain stems from the widespread use of Python's `pickle` serialization format for saving and distributing model weights. Platforms like Hugging Face Hub host thousands of models stored in formats (`.pkl`, `.pt`, `.bin`) that rely on pickle for deserialization. The `pickle` module is fundamentally insecure because it can be used to execute arbitrary code during the object loading process. An attacker can create a malicious model file containing a serialized object whose `__reduce__` method is crafted to call a system command (e.g., `os.system('curl ...')`). When a victim downloads this model and loads it using `torch.load()` or `pickle.load()`, the payload executes, granting the attacker RCE on the user's machine. This affects data scientists, ML engineers, and any application that dynamically loads models from untrusted sources. Despite long-standing warnings in the Python documentation, the practice remained common due to its convenience. The impact is severe, potentially leading to compromised developer workstations, stolen credentials, or attacks on production ML inference servers. This vulnerability highlighted the urgent need for the community to adopt safer, code-free serialization formats.
Affected Systems
Testing Guide
1. **Do NOT run this on your main machine.** Use a disposable VM or container. 2. Create a malicious pickle file with the following Python code: ```python import pickle import os class RCE: def __reduce__(self): cmd = ('touch /tmp/pwned') return (os.system, (cmd,)) with open("malicious.pkl", "wb") as f: pickle.dump(RCE(), f) ``` 3. In a separate script, attempt to load the file: ```python import pickle with open("malicious.pkl", "rb") as f: pickle.load(f) ``` 4. Check if the file `/tmp/pwned` was created. If so, the environment is vulnerable to RCE via pickle deserialization.
Mitigation Steps
1. **Use SafeTensor Format**: Prioritize loading models exclusively in the `safetensors` format. It is a secure alternative designed specifically to prevent arbitrary code execution. 2. **Scan Models Before Loading**: Use security scanners like `picklescan` or Hugging Face's built-in malware scanner to check model files for malicious payloads before deserialization. 3. **Never Load Pickles from Untrusted Sources**: Establish a strict policy against loading pickled files downloaded from the internet or from unverified sources. 4. **Isolate Model Loading**: If loading a pickle file is unavoidable, do so in a minimal, sandboxed environment with no network access or sensitive data.
Patch Details
This is a design flaw in the pickle format, not a bug in a specific library. The ecosystem is migrating to `safetensors` as the secure alternative.