# Malicious Model RCE - PyTorch weights_only Bypass in vLLM Launch

- **Severity:** High
- **Signature ID:** `7b3f1c9e-2d54-4a86-9f1b-6c0e8a4d5b72`
- **MITRE ATLAS:** AML.T0010 (AI Supply Chain Compromise)
- **OWASP:** LLM03 (Supply Chain)

## Summary

PyTorch model files saved in the old pickle format can run arbitrary code when loaded, and a flaw in versions before 2.6.0 means even the 'safe' weights_only setting doesn't stop it. This rule flags command lines that load models this way, especially from untrusted or writable locations.

## How the attack works

An attacker plants or points a victim's vLLM deployment at a model file using the legacy pickle-based formats (.bin, .pt, .pth, .ckpt, .pkl) instead of the safer safetensors format. Loading such a file executes any code embedded in it, because PyTorch's pickle deserializer runs arbitrary Python during unpickling. The rule watches for three separate warning signs: vLLM being told to use the pickle loader or fetch a model from a world-writable temp directory; a script directly calling torch.load or similar deserialization functions alongside signs the payload is untrusted (weights_only=False, a remote URL, a scratch-directory path); or an environment variable that globally disables the weights_only safety check for the whole process.

## Why it matters

If successful, this gives an attacker code execution on the machine serving the model, which can lead to data theft, lateral movement, or further compromise of the AI infrastructure.

## What you can do

- Convert and distribute models in the safetensors format instead of pickle-based .bin/.pt/.pth/.ckpt/.pkl files.
- Never load model weights from world-writable directories like /tmp, /var/tmp, or /dev/shm.
- Upgrade PyTorch to 2.6.0 or later, since the weights_only flag does not protect earlier versions.
- Restrict who can set environment variables or launch commands for model-serving processes, and review any use of TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD.

## Known benign look-alikes

- Legitimate vLLM deployment of an older Hugging Face repo that ships only PyTorch .bin/.pt weights and therefore requires --load-format pt or a .bin model path.
- ML engineers inspecting a trusted local checkpoint with a one-liner such as 'python -c "import torch; print(torch.load(''ckpt.pth'').keys())"'.
- Model conversion or quantisation pipelines that read a .bin checkpoint from a scratch directory (/tmp, /dev/shm) before re-serialising it to safetensors.
- Deliberate use of TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD=1 on PyTorch >= 2.6.0 to load a known-good legacy checkpoint containing non-tensor objects.
- CI fixture checkpoints staged in /tmp by a job whose command line does not contain pytest/conftest markers and therefore escapes the CI filter.

## References

- https://pytorch.org/docs/stable/generated/torch.load.html
- https://atlas.mitre.org/techniques/AML.T0010
- https://attack.mitre.org/techniques/T1204/002/
- https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/

---
Source: https://www.netzilo.com/threats/vllm-torch-weights-only-bypass-rce
