Pickle vs. GGUF: Two Serialization Philosophies, Two Threat Models

▶ Watch (03:20)

Pickle is Python’s native serializer. It can capture tensors, classes, and functions. That flexibility is also its flaw: it lets data become code at load time. GGUF was built for large language models. It stores metadata that shapes how a model handles prompts and chat templates, but it does not execute code on load. The split matters. Pickle attacks fire the moment you open the file. GGUF attacks fire when you use it.

“pickle doesn’t just store data, it stores behavior” — Octavian Purcaru

Wired, Databricks, and Hacker News have all run stories on malicious models slipping through Hugging Face. Different sources, same finding: model files are a live infection vector.

Pickle RCE via numpy PrivateUtils: CVInvokeAI Case Study

▶ Watch (07:25)

CVInvokeAI shipped with scan_file set to false by default. When that bug was reported and patched, the patch introduced a new one: the scan delegated to picklescan, a third-party tool that missed certain opcodes entirely. The bypass used numpy.testing._private.utils.run_string, a function picklescan didn’t flag. A crafted pickle file called it via the GLOBAL and REDUCE opcodes, passing an attacker-supplied string that imported os and ran arbitrary shell commands. The numpy PrivateUtils pickle payload achieving callback (08:09) confirms the full exploitation path, ending with a curl callback to an attacker-controlled server.

GGUF Template Injection RCE: Llama.cpp Jinja2 Case Study

▶ Watch (09:57)

Llama.cpp read the GGUF chat_template field from model metadata and passed it straight into a plain Jinja2 environment, no sandbox. Jinja2 compiled the template in the constructor and evaluated any embedded expressions at prompt-construction time. An attacker embedding a crafted template could walk Python’s __subclasses__ chain, import os, then pipe a netcat command through a FIFO to open a GGUF Jinja2 reverse shell to attacker VPS (10:54). The exploit fires not when the model loads but when the application first builds a prompt from it.

Defenses: Sandboxing Pickle and Hardening GGUF Metadata

▶ Watch (13:16)

For pickle, avoid it when possible. When you must use it, set weights_only=True in PyTorch, restrict serialization to safe types, and run deserialization in a sandbox with no network access and minimal privileges. For GGUF, never pass chat-template metadata into a templating engine. Treat it as data, validate it, and disable automatic rendering paths in production. Across both formats, enforce origin checks and require signatures on every artifact before it enters your pipeline.

“Pickle is fine. If it comes from the internet or a user, sandbox it or avoid it.” — Octavian Purcaru

Q&A

Can we completely stop using pickle for this kind of activity? No — stop using it for untrusted data only; pickle from inside your own pipeline is fine, but sandbox it or avoid it when the source is the internet or a user. ▶ 15:06

Does EDR actually detect these attacks? Not natively at this stage — EDR catches the activity later, at the binary-manifest phase when the payload reaches a C2 or shows anomalous behavior, not at deserialization time. ▶ 15:36

Notable Quotes

a model file is executable input until proven otherwise Octavian Purcaru · ▶ 1:12

pickle doesn’t just store data, it stores behavior Octavian Purcaru · ▶ 6:28

Pickle is fine. If it comes from the internet or a user, sandbox it or avoid it. Octavian Purcaru · ▶ 15:18

Key Takeaways

  • Never deserialize a pickle file you did not generate yourself; treat every downloaded model as executable input.
  • Load PyTorch models with weights_only=True and run deserialization inside a sandboxed environment with no network access.
  • Never render GGUF chat-template metadata through a templating engine; treat all model metadata as untrusted data, not code.

About the Speakers

Octavian Purcaru

Octavian is an Incident Response Commander in Adobe’s SOC team and a cybersecurity consultant. He focuses on incident response, helping organizations detect, investigate, and mitigate cyber threats. As a consultant for NGOs, he assists in strengthening their security posture and resilience against cyber attacks. He also explores emerging AI capabilities in the cyber realm to enhance defense strategies.

Văşcuță Denis

Hi! I’m Denis Vascuta. Been passionate about cybersecurity ever since I was in 9th grade. I participated in many CTFs, even took part in ECSC (European Cyber Security Challenge) twice, having the chance to represent my country (Romania).