PyTorch's default checkpoint format is Python's pickle module, and pickle's own documentation carries a blunt warning: never unpickle data from an untrusted source, because its __reduce__ mechanism can execute arbitrary code the instant a file is deserialized. That warning has been in the Python docs for over a decade, yet it's routinely ignored across the ML ecosystem, where "download a checkpoint and load it" is a one-line habit for millions of developers. JFrog's security research team quantified the resulting exposure in March 2024, scanning public Hugging Face repositories and finding roughly 100 model files carrying malicious pickle payloads — reverse shells embedded via __reduce__, with about 95% targeting PyTorch, giving attackers a persistent backdoor on any machine that loaded them. The problem didn't go away with better tooling: in December 2025, JFrog disclosed three zero-days in PickleScan, the open-source scanner integrated into Hugging Face's scanning pipeline, including CVE-2025-10155 (CVSS 9.3), which let a malicious file evade detection by carrying a .bin or .pt extension that caused the scanner to apply the wrong parsing logic instead of inspecting the actual content. A model checkpoint is now a build-pipeline artifact with the same trust problem as a pip install, and most organizations have no inventory of where their weights came from, who signed them, or what code runs when they load.
Why is a model checkpoint as dangerous as a malicious package?
A model checkpoint is dangerous for the same structural reason a malicious PyPI package is: both are files your build pipeline pulls from a third party and executes with your permissions, often with no human reviewing the contents first. When a torch.load() call deserializes a .pt or .bin file, pickle's __reduce__ method lets the file specify an arbitrary function and arguments to run during load — not after, not conditionally, but as a side effect of opening the file. JFrog's March 2024 research demonstrated this is not theoretical: the roughly 100 malicious files it found on Hugging Face didn't need a user to run anything explicit, only to load the "model" the way every tutorial tells them to. Because CI/CD pipelines increasingly auto-pull model versions the same way they auto-pull dependency updates, a compromised or typosquatted model repository can achieve code execution inside a build environment exactly like a compromised npm or PyPI package can — except most SCA tooling built for source-code dependencies never looks inside a .bin file at all.
Does converting to a safer format actually solve the problem?
Converting to safetensors — Hugging Face's format that stores only raw tensor data with no executable opcodes — closes the direct pickle-RCE path, but it doesn't secure the pipeline around it. Safetensors was built specifically so loading a model can never trigger arbitrary code execution, and it's now the default output format encouraged across the Hugging Face Hub. The catch, documented by security research firm HiddenLayer in 2024, is that the conversion service itself became an attack surface: Hugging Face ran a hosted bot that would automatically convert user-submitted pickle files to safetensors, and HiddenLayer showed a malicious pull request submitted to that conversion pipeline could compromise the process doing the converting — turning a safety mechanism into a new injection point. The lesson generalizes past this one incident: swapping a risky file format for a safe one only helps if every tool that touches the artifact along the way, including automated conversion and scanning infrastructure, is itself trusted and verified. Format safety and pipeline provenance are separate problems, and fixing one without the other leaves a real gap.
What is an ML-BOM and how does it differ from a code SBOM?
An ML-BOM (Machine Learning Bill of Materials) applies the same idea as a code SBOM — a structured, queryable inventory — to model artifacts instead of software packages, but it tracks fields a package manifest was never designed to hold. CycloneDX added native ML-BOM support in version 1.5, released in June 2023, and expanded it further in 1.6 (ratified by Ecma International as ECMA-424 in June 2024) and then 1.7, released in October 2025 and adopted as the second edition of that same standard that December, to cover model architecture, training and inference configuration, dataset references, and quantitative evaluation metrics — none of which map cleanly onto a package.json or requirements.txt entry. SPDX has pursued a parallel AI profile with similar goals. Where a code SBOM answers "which library versions and licenses are in this build," an ML-BOM is built to answer "which base model, which fine-tune dataset, whose weights, hashed and signed how." OWASP recognized the gap between the two specs and launched its AIBOM Project in 2025 to build an open-source generator for Hugging Face models and to assess where CycloneDX and SPDX still fall short for real-world model tracking.
What should a model provenance record actually contain?
A useful model provenance record needs to answer four questions an SCA tool never asks: where did these weights come from, are they signed, what code would run if I loaded them, and what data trained them. That means capturing weight origin (a named registry or publisher, not just "downloaded from the internet") and a content hash to detect silent tampering; a cryptographic signature and the trust anchor or transparency log it verifies against; a scan result for embedded executable code in pickle-format files, since a hash alone doesn't tell you a payload is absent; and dataset lineage for any fine-tune, including license status, so a copyleft or PII-bearing dataset doesn't end up baked into a production model with no paper trail. This is materially more than a code SBOM captures, and it's why treating model files as "just another dependency" under existing SCA tooling misses the categories of risk that are unique to weights — backdoored parameters and training-data provenance have no analogue in a package-lock.json.
How Safeguard Helps
Safeguard treats AI artifacts as first-class objects with their own SBOM — an AI-BOM — emitted in CycloneDX ML-BOM extension format and SPDX 3.0 AI profile, so model weights get the same queryable inventory that source dependencies already have. It captures weight provenance and hash on ingest from Hugging Face, MLflow, SageMaker, Vertex AI, and other registries, scans checkpoints for pickle-embedded executable code before they reach a production loader, and runs Eagle, Safeguard's statistical model, to score weights for trojan triggers and class-level backdoors. Load-time policy enforcement blocks unsigned weights or unsafe code outright — a served model that fails hash, signature, or code-safety verification simply won't load — and every fine-tune produces a signed lineage attestation so a security team can answer "show me every dataset that touched this model" in one query instead of an audit trail reconstructed by hand.