CVE-2026-90777 Overview
CVE-2026-90777 is an insecure deserialization vulnerability [CWE-502] in ESPnet, an end-to-end speech processing toolkit. Versions before 202609 load pretrained model checkpoints with torch.load(weights_only=False), which permits arbitrary Python code execution during deserialization. An attacker who supplies a malicious checkpoint file can achieve remote code execution when a victim loads it through the initialization or fine-tuning path. The flaw affects downstream users who consume third-party ESPnet checkpoints from model hubs, shared storage, or untrusted URLs.
Critical Impact
Loading an attacker-controlled ESPnet checkpoint executes arbitrary code in the context of the user running training or inference, leading to full host compromise.
Affected Products
- ESPnet versions prior to v.202609
- ESPnet workflows invoking load_pretrained_model in espnet2/torch_utils/
- ESPnet pipelines using average_nbest_models and speechlm/bin/inference code paths
Discovery Timeline
- 2026-09-13 - CVE-2026-90777 published to NVD
- 2026-09-14 - Last updated in NVD database
Technical Details for CVE-2026-90777
Vulnerability Analysis
ESPnet's pretrained model loading logic invokes PyTorch's torch.load with weights_only=False. This setting instructs PyTorch to fully unpickle the checkpoint file, including arbitrary Python objects and their __reduce__ methods. Any attacker able to influence the checkpoint file therefore controls code execution in the loading process.
The vulnerable code path resides in espnet2/torch_utils/load_pretrained_model.py and is reachable through initialization, fine-tuning, model averaging in average_nbest_models.py, and SpeechLM inference. Because ESPnet is commonly used with checkpoints distributed via Hugging Face, GitHub releases, and shared research storage, the trust boundary between a checkpoint file and executable code is easily crossed.
Root Cause
The root cause is unsafe use of Python's pickle protocol via torch.load(..., weights_only=False). Pickle deserialization is Turing-complete and treats serialized objects as executable instructions. ESPnet did not gate this behavior behind an explicit opt-in, so any checkpoint path could trigger it silently.
Attack Vector
Exploitation requires an attacker to deliver a crafted checkpoint file to a victim. Delivery vectors include typosquatted model hub entries, compromised model repositories, phishing links, or malicious pull requests that reference attacker-hosted URLs. When the victim loads the checkpoint through ESPnet's initialization or fine-tuning path, embedded reducer objects execute arbitrary Python code with the privileges of the training process.
# Security patch in espnet2/main_funcs/average_nbest_models.py
# Introduces safe_torch_load wrapper; unsafe fallback removed
import torch
from typeguard import typechecked
+from espnet2.torch_utils.safe_torch_load import safe_torch_load
from espnet2.train.reporter import Reporter
Source: GitHub Commit 91ca045
# Security patch in espnet2/speechlm/bin/inference.py
from espnet2.speechlm.dataloader.iterator import DataIteratorFactory
from espnet2.speechlm.model import _all_job_types
from espnet2.speechlm.utils.data import to_device
+from espnet2.torch_utils.safe_torch_load import safe_torch_load
def get_parser() -> argparse.ArgumentParser:
Source: GitHub Commit 91ca045
The patch routes checkpoint loading through safe_torch_load, removing the automatic unsafe fallback and requiring explicit opt-in when non-tensor objects must be deserialized.
Detection Methods for CVE-2026-90777
Indicators of Compromise
- Python processes spawning shells, curl, wget, or compilers immediately after invoking torch.load or ESPnet CLI entry points.
- Checkpoint files (.pth, .pt, .ckpt) sourced from unverified URLs, mirrors, or personal repositories rather than the official ESPnet release channel.
- Unexpected outbound network connections from training hosts shortly after model load events.
- Modified or newly written files in home directories, SSH configuration paths, or crontabs after loading a third-party checkpoint.
Detection Strategies
- Instrument Python environments to log calls to torch.load with weights_only=False and alert on checkpoints loaded from non-approved paths.
- Use static analysis to flag ESPnet installations pinned below v.202609 across data science hosts and CI runners.
- Correlate parent-child process telemetry to detect Python interpreters spawning unexpected system binaries during model load operations.
Monitoring Recommendations
- Monitor ML workstations, GPU clusters, and Jupyter servers for anomalous process trees rooted at ESPnet or torch entry points.
- Track network egress from training environments to catch reverse shells or data exfiltration initiated during checkpoint deserialization.
- Audit checkpoint download history and enforce integrity verification (SHA-256) against a curated allowlist.
How to Mitigate CVE-2026-90777
Immediate Actions Required
- Upgrade ESPnet to v.202609 or later on all training, inference, and CI systems.
- Inventory existing checkpoint files, remove any of untrusted provenance, and re-download from official ESPnet release channels.
- Restrict outbound network access from ML workloads to limit blast radius if a malicious checkpoint executes.
- Run ESPnet workloads under least-privilege service accounts, not as root or as developer accounts with broad access.
Patch Information
The fix is delivered in ESPnet release v.202609 via commit 91ca045fc179f29bc7b7fe05cd852aea65310003. The patch introduces the safe_torch_load helper and removes the implicit unsafe fallback across average_nbest_models.py, speechlm/bin/inference.py, and related loaders. See the GitHub Security Advisory GHSA-64f6-3gqc-r926 and the VulnCheck ESPnet RCE Advisory for full details.
Workarounds
- Load only checkpoints produced in-house or verified against a known-good SHA-256 hash.
- Where possible, convert checkpoints to the safetensors format, which is not vulnerable to pickle-based code execution.
- Execute untrusted checkpoint loads inside disposable sandboxes or containers with no credentials, no network egress, and no persistent storage.
# Upgrade ESPnet to the patched release
pip install --upgrade "espnet>=202609"
# Verify installed version
python -c "import espnet; print(espnet.__version__)"
# Verify checkpoint integrity before loading
sha256sum model.pth
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.