Principle:Trailofbits Fickling Pickle Payload Injection
| Knowledge Sources | |
|---|---|
| Domains | Security_Research, Red_Team, Deserialization |
| Last Updated | 2026-02-14 14:00 GMT |
Overview
A technique for injecting arbitrary Python code into PyTorch model files by modifying the embedded pickle payload, used for security research, scanner benchmarking, and red team exercises.
Description
Pickle Payload Injection modifies a legitimate PyTorch model file to include additional Python code that will execute when the model is loaded. This is used exclusively for defensive security purposes: testing whether security scanners detect injected payloads, benchmarking scanner accuracy, and demonstrating attack vectors to stakeholders.
Two injection modes exist:
- Insertion mode: Modifies the pickle opcodes directly by inserting GLOBAL/REDUCE sequences that call builtins.exec with the payload string. The original model data is preserved — the payload runs before the model is returned. This is a bytecode-level modification.
- Combination mode: Wraps the original model in a BaseInjection class whose __reduce__ method returns (eval, (payload,)). The entire model is re-serialized via torch.save. This is a Python-level modification.
Usage
Use this principle for security research: creating test samples for scanner evaluation, demonstrating supply chain attack vectors, or building training datasets for ML security tools. Always use on isolated test environments with models you own.
Theoretical Basis
Pickle injection exploits the REDUCE opcode, which calls a function from the stack:
# Insertion mode: Injects opcodes into existing pickle stream
# The injected opcodes encode:
GLOBAL "builtins" "exec" # Push exec function
STRING "payload code" # Push payload string
TUPLE # Pack arguments
REDUCE # Call exec(payload)
# Combination mode: Uses Python __reduce__ protocol
class Injection:
def __reduce__(self):
return eval, (payload_string,)