Llama Drama: A Malicious Model File That Runs Code
The model file isn't just data — its chat template was run as code the moment you loaded it.
| When | May 2024 |
|---|---|
| Target | llama-cpp-python |
| Researcher | retr0reg (Patrick Peng); named by Checkmarx |
| Technique | Jinja2 template injection (SSTI) via model metadata |
| CVE | CVE-2024-34359 — CVSS 9.6 (Critical) |
- 1An attacker publishes a GGUF model whose chat-template metadata carries an SSTI payload
- 2A victim loads the model with a vulnerable llama-cpp-python
- 3The template renders through an unsandboxed Jinja2 environment and executes code
What happened
In 2024, Llama Drama (CVE-2024-34359) showed that a malicious model file could execute code in llama-cpp-python. The library rendered a model's chat template — stored in its GGUF metadata — through a full, unsandboxed Jinja2 environment. A crafted template carried a server-side template injection that ran arbitrary Python the moment the model was loaded. Thousands of Hugging Face models were potentially affected; fixed in 0.2.72.
How the attack worked
Chat templates legitimately format prompts, and llama-cpp-python evaluated them with Jinja2. Because that environment wasn't sandboxed, template syntax could reach Python internals (classic SSTI) — so the 'model' was really a code-execution payload wearing model metadata.
Root cause
Untrusted model metadata was processed by a powerful template engine with no sandbox — treating a downloaded artifact's contents as safe to evaluate.
Why it matters
Pickle scanners look for malicious serialization; this hides in an ordinary-looking template string, so 'safetensors, not pickle' is not enough. The loader itself is an attack surface.
How to prevent it
- Update to a version that sandboxes template rendering.
- Treat third-party model files as untrusted code, not inert data.
- Prefer models from sources you can verify; check provenance.
FAQ
How does a model file run code?
GGUF model files carry a chat template in their metadata. llama-cpp-python rendered it with a full, unsandboxed Jinja2 environment — so a template crafted with SSTI payloads executed Python (RCE) when the model was loaded, before you even ran it.
Why is this different from a pickle-model attack?
It's not pickle deserialization. The weaponised artifact is the template string inside otherwise-normal model metadata, so pickle scanners miss it — the danger is in how the loader processes model config.
How do you defend?
Update to a patched version that sandboxes template rendering, treat third-party model files as untrusted code, and prefer models from sources you can verify.