CVE-2026-31238: Ludwig: RCE via unsafe pickle deserialization in model serve
GHSA-xp5q-5q7g-q26r CRITICAL CISA: TRACK*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.
What is the risk?
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.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| PyTorch | pip | <= 0.10.4 | No patch |
Do you use PyTorch? You're affected.
How severe is it?
What is the attack surface?
What should I do?
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.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
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?
CVE-2026-31238 has a CVSS v3.1 base score of 9.8 (CRITICAL). The EPSS exploitation probability is 0.50%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0010.003 Model AML.T0011.000 Unsafe AI Artifacts AML.T0018.002 Embed Malware AML.T0049 Exploit Public-Facing Application Compliance Controls Affected
What are the technical details?
Original Advisory
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.
Weaknesses (CWE)
CWE-502 — Deserialization of Untrusted Data: The product deserializes untrusted data without sufficiently ensuring that the resulting data will be valid.
- [Architecture and Design, Implementation] If available, use the signing/sealing features of the programming language to assure that deserialized data has not been tainted. For example, a hash-based message authentication code (HMAC) could be used to ensure that data has not been modified.
- [Implementation] When deserializing data, populate a new object rather than just deserializing. The result is that the data flows through safe input validation and that the functions are safe.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H References
Timeline
Related Vulnerabilities
CVE-2024-5452 9.8 pytorch-lightning: RCE via deepdiff Delta deserialization
Same package: torch CVE-2023-43654 9.8 TorchServe: SSRF + RCE via unrestricted model URL loading
Same package: torch CVE-2022-45907 9.8 PyTorch: RCE via unsafe eval in JIT annotations
Same package: torch CVE-2022-0845 9.8 pytorch-lightning: code injection enables full RCE
Same package: torch CVE-2024-35198 9.8 TorchServe: URL bypass enables arbitrary model loading
Same package: torch