CVE-2026-31238: Ludwig: RCE via unsafe pickle deserialization in model serve
AWAITING NVDLudwig's model serving command loads PyTorch model files using `torch.load()` without the `weights_only=True` parameter, meaning any model file deserialized at startup has unrestricted Python pickle execution capabilities — a well-understood, trivially exploitable primitive for achieving arbitrary code execution. This affects any team running `ludwig serve` in production or staging environments, particularly in MLOps pipelines that automatically pull and serve models from shared registries or external sources. While no EPSS score or active exploitation has been recorded yet, pickle-based RCE in ML tooling is a heavily documented and tooled attack class requiring minimal attacker sophistication. Immediate action: do not load Ludwig models from untrusted or unverified sources, audit model file provenance controls, and use `fickling` or `picklescan` to inspect model files; upgrade Ludwig once a patched release is available.
Risk Assessment
High risk despite absent CVSS data. Pickle deserialization RCE is a known-high-severity class — CVSS typically lands 9.8 for network-reachable unauthenticated variants. The attack surface is the model server process, which may be internet-facing or accessible to internal shared storage. Exploitation requires only that an attacker can place a malicious model file in the path Ludwig loads from — no authentication needed against the framework itself. The `weights_only=True` parameter exists precisely to prevent this class of attack; omitting it is a well-known insecure default in PyTorch ecosystems.
Attack Kill Chain
Severity & Risk
Recommended Action
5 steps-
Upgrade Ludwig to a version beyond 0.10.4 once a patched release is published — monitor the Ludwig GitHub repository for a fix that enforces
weights_only=True. -
Immediate workaround: restrict model file sources strictly to internally-signed, provenance-tracked artifacts; never load externally-supplied or user-provided
.pt/.ckptfiles. -
Scan all PyTorch model files with
fickling(Trail of Bits) orpicklescanbefore loading — both detect embedded pickle payloads. -
Migrate model storage to SafeTensors format (CWE-502-immune by design) where the pipeline permits.
-
Apply least-privilege to the model server process — run in a restricted container with no cloud metadata access, minimal network egress, and no write access to secrets.
Classification
Compliance Impact
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-31238?
Ludwig's model serving command loads PyTorch model files using `torch.load()` without the `weights_only=True` parameter, meaning any model file deserialized at startup has unrestricted Python pickle execution capabilities — a well-understood, trivially exploitable primitive for achieving arbitrary code execution. This affects any team running `ludwig serve` in production or staging environments, particularly in MLOps pipelines that automatically pull and serve models from shared registries or external sources. While no EPSS score or active exploitation has been recorded yet, pickle-based RCE in ML tooling is a heavily documented and tooled attack class requiring minimal attacker sophistication. Immediate action: do not load Ludwig models from untrusted or unverified sources, audit model file provenance controls, and use `fickling` or `picklescan` to inspect model files; upgrade Ludwig once a patched release is available.
Is CVE-2026-31238 actively exploited?
No confirmed active exploitation of CVE-2026-31238 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-31238?
1. Upgrade Ludwig to a version beyond 0.10.4 once a patched release is published — monitor the Ludwig GitHub repository for a fix that enforces `weights_only=True`. 2. Immediate workaround: restrict model file sources strictly to internally-signed, provenance-tracked artifacts; never load externally-supplied or user-provided `.pt`/`.ckpt` files. 3. Scan all PyTorch model files with `fickling` (Trail of Bits) or `picklescan` before loading — both detect embedded pickle payloads. 4. Migrate model storage to SafeTensors format (CWE-502-immune by design) where the pipeline permits. 5. Apply least-privilege to the model server process — run in a restricted container with no cloud metadata access, minimal network egress, and no write access to secrets.
What systems are affected by CVE-2026-31238?
This vulnerability affects the following AI/ML architecture patterns: model serving, ML inference pipelines, MLOps pipelines, model registries, training pipelines.
What is the CVSS score for CVE-2026-31238?
No CVSS score has been assigned yet.
Technical Details
NVD Description
The Ludwig framework thru 0.10.4 is vulnerable to insecure deserialization (CWE-502) in its model serving component. When starting a model server with the ludwig serve command, the framework loads model weight files using torch.load() without enabling the security-restrictive weights_only=True parameter. This default behavior allows the deserialization of arbitrary Python objects via the pickle module. An attacker can exploit this by providing a maliciously crafted PyTorch model file, leading to arbitrary code execution on the system hosting the Ludwig model server.
Exploitation Scenario
An adversary targeting an organization using Ludwig for model serving generates a malicious PyTorch model file using publicly available tools (e.g., `fickling` in write mode or a custom pickle payload) that embeds a reverse shell or credential exfiltration command. The attacker uploads this file to a shared model registry, S3 bucket with misconfigured permissions, or submits it via an MLOps API that accepts model uploads. When the victim's automated pipeline runs `ludwig serve --model-path <malicious.pt>`, `torch.load()` deserializes the pickle payload without restriction, executing the adversary's code with the server process's privileges — granting lateral movement into internal systems or cloud infrastructure.
Timeline
Related Vulnerabilities
CVE-2025-59528 10.0 Flowise: Unauthenticated RCE via MCP config injection
Same attack type: Supply Chain CVE-2024-2912 10.0 BentoML: RCE via insecure deserialization (CVSS 10)
Same attack type: Supply Chain CVE-2023-3765 10.0 MLflow: path traversal allows arbitrary file read
Same attack type: Supply Chain CVE-2025-5120 10.0 smolagents: sandbox escape enables unauthenticated RCE
Same attack type: Supply Chain CVE-2026-21858 10.0 n8n: Input Validation flaw enables exploitation
Same attack type: Code Execution
AI Threat Alert