CVE-2026-31249 Overview
CVE-2026-31249 is an insecure deserialization vulnerability [CWE-502] in CosyVoice, an open-source speech generation toolkit from FunAudioLLM. The flaw exists in the make_parquet_list.py data processing script through commit 6e01309e01bc93bbeb83bdd996b1182a81aaf11e. The script calls torch.load() on PyTorch .pt files without setting the weights_only=True security parameter. This permits Python's pickle module to deserialize arbitrary objects from attacker-controlled files. Processing a malicious .pt file results in arbitrary code execution on the victim's system.
Critical Impact
Attackers who supply malicious .pt files within a CosyVoice data directory can achieve arbitrary code execution when a victim runs make_parquet_list.py against that directory.
Affected Products
- CosyVoice (FunAudioLLM) through commit 6e01309e01bc93bbeb83bdd996b1182a81aaf11e dated 2025-10-21
- The make_parquet_list.py data processing tool
- Any downstream project bundling vulnerable CosyVoice training pipelines
Discovery Timeline
- 2026-05-11 - CVE-2026-31249 published to NVD
- 2026-05-12 - Last updated in NVD database
Technical Details for CVE-2026-31249
Vulnerability Analysis
CosyVoice ships a preprocessing utility, make_parquet_list.py, that aggregates utterance embeddings, speaker embeddings, and speech tokens into Parquet datasets. The script loads each embedding artifact from disk using torch.load(). PyTorch's loader delegates to Python's pickle module by default, which executes arbitrary callables encoded in the serialized stream through the __reduce__ protocol.
Because the script does not pass weights_only=True, any .pt file inside the target directory becomes an execution primitive. An attacker who can place or substitute files in a dataset directory controls the deserialization payload. The vulnerability requires no authentication and no user interaction beyond the standard preprocessing workflow.
Root Cause
The root cause is unsafe use of torch.load() on untrusted input. PyTorch documents the weights_only parameter specifically to restrict deserialization to tensor data and prevent pickle gadgets from running. The vulnerable script omits this parameter, so the loader defaults to full pickle semantics for every .pt artifact it processes.
Attack Vector
The attack vector is delivery of a malicious .pt file into a directory consumed by make_parquet_list.py. Likely delivery channels include shared dataset archives, community-published speaker embeddings, fine-tuning data hosted on model hubs, and supply chain compromise of training corpora. When the victim runs the preprocessing tool, the embedded __reduce__ payload executes with the privileges of the invoking user.
No verified public exploit code is referenced in the advisory. The vulnerability mechanism mirrors the well-documented pickle.loads() gadget pattern: a serialized object whose __reduce__ method returns a callable such as os.system together with attacker-supplied arguments. Refer to the CosyVoice repository and the CVE-2026-31249 analysis for additional technical context.
Detection Methods for CVE-2026-31249
Indicators of Compromise
- Unexpected child processes spawned by Python interpreters running make_parquet_list.py or other CosyVoice scripts.
- .pt files in dataset directories whose size, hash, or provenance does not match the upstream source.
- Outbound network connections initiated from training hosts during dataset preprocessing.
- New files or scheduled tasks created by the user account that executed the preprocessing pipeline.
Detection Strategies
- Hunt for invocations of torch.load without weights_only=True across internal ML codebases using static analysis or grep-based audits.
- Monitor process lineage on ML training hosts: a python process executing make_parquet_list.py should not spawn shells, package managers, or networking utilities.
- Validate cryptographic hashes of .pt files against a trusted manifest before preprocessing runs.
Monitoring Recommendations
- Enable command-line and process-creation logging on workstations and GPU servers used for model training.
- Alert on file writes to ~/.ssh, cron locations, and persistence paths originating from Python ML workloads.
- Capture egress telemetry from data science environments to detect unexpected callbacks from deserialization payloads.
How to Mitigate CVE-2026-31249
Immediate Actions Required
- Stop running make_parquet_list.py against any dataset whose .pt files are not fully trusted and verified.
- Audit existing CosyVoice clones for the vulnerable commit 6e01309e01bc93bbeb83bdd996b1182a81aaf11e and quarantine derived artifacts.
- Patch local copies by passing weights_only=True to every torch.load() call in CosyVoice preprocessing scripts.
- Rotate credentials and inspect hosts that have processed third-party .pt files since the affected commit was deployed.
Patch Information
No official vendor advisory or fixed release is referenced in the NVD entry at publication. Maintainers and operators should apply the upstream guidance for torch.load(), which is to set weights_only=True when loading checkpoints from untrusted sources, and to track the CosyVoice repository for a security release.
Workarounds
- Modify make_parquet_list.py to invoke torch.load(path, weights_only=True, map_location='cpu') for embeddings and tokens.
- Execute preprocessing inside an isolated container or sandbox with no outbound network access and a read-only filesystem outside the working directory.
- Verify dataset integrity by enforcing signed manifests and SHA-256 checksums before any .pt file is consumed.
- Restrict write access to dataset directories so only trusted automation, not interactive users or external pipelines, can place .pt artifacts.
# Configuration example: safer invocation pattern for torch.load
# Replace unsafe calls in make_parquet_list.py
# data = torch.load(path)
# with:
# data = torch.load(path, weights_only=True, map_location='cpu')
# Verify dataset integrity before preprocessing
find ./data -name '*.pt' -print0 | xargs -0 sha256sum > current.sha256
diff trusted.sha256 current.sha256 || { echo 'Dataset integrity check failed'; exit 1; }
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


