Static model scanning is a control, not a guarantee. Here is why pickle formats run code on load, where scanners fall short, and how defenders build real defense in depth around model ingestion.
A clean model scanner result confirms one narrow fact: no known-bad signature matched in the scanner version that ran. It does not confirm that the artifact is safe to load. That gap matters, because pickle-based model formats execute code during deserialization, which makes loading an untrusted model roughly equivalent to running an untrusted program. So if a Hugging Face model passes the platform security scanner, is it actually safe to load in production? Not necessarily, and researchers keep publishing ways to slip malicious pickles past the exact scanners that platforms rely on.
The single most important number for buyers to internalize arrived in July 2026. In the non-peer-reviewed preprint ShadowPickle, the best-performing attack variant, which the authors call "Overwritten," reached a 63 percent evasion rate across ten state-of-the-art scanners (Pradhan, Nambiar, and Soremekun, arXiv:2607.17503). That figure is not a hypothetical. It sits on top of a 2025 disclosure cycle in which Sonatype, headquartered in Maryland, documented four separate ways to bypass PickleScan, the open-source tool that sits inside the malware-scanning stack of major model hubs (Sonatype, Bypassing PickleScan).
This post is the Stingrai research team's canonical 2026 reference on why a clean model scan is not a safe model. It draws on four primary publishers: Sonatype's security research, the United States National Vulnerability Database, the arXiv ShadowPickle preprint, and Hugging Face's own SafeTensors documentation. Lead data spans the 2025 CVE disclosures and the July 2026 ShadowPickle preprint, the freshest research available as of July 2026. Every figure below links back to its primary publisher, so any claim can be audited inline, and the ShadowPickle numbers are attributed to the specific variant and labeled as a preprint rather than a settled result.
TL;DR: the numbers that matter
ShadowPickle "Overwritten" evasion rate (2026): 63 percent across ten scanners, attributed to that specific variant in a non-peer-reviewed preprint (arXiv:2607.17503).
Model hubs evaded by ShadowPickle (2026): four, alongside the ten scanners, per the same preprint (arXiv:2607.17503).
PickleScan bypasses disclosed by Sonatype (2025): four CVEs, CVE-2025-1716, CVE-2025-1889, CVE-2025-1944, and CVE-2025-1945 (Sonatype).
CVE-2025-1716 severity (2025): CVSS 3.1 base score 9.8, critical, for an incomplete deny list that let a crafted model reach
pip.main()(NVD).CVE-2025-1889 severity (2025): CVSS 3.1 base score 9.8, critical, for scanning only standard pickle file extensions (NVD).
CVE-2025-1945 severity (2025): CVSS 3.1 base score 9.8, critical, for missing pickles when ZIP flag bits are modified while PyTorch still loads them (NVD).
CVE-2025-1944 severity (2025): CVSS 3.1 base score 6.5, medium, for a ZIP manipulation that crashes the scanner while PyTorch still parses the archive (NVD).
PickleBench difficulty gain (2026): up to 25.6 percent harder than three prior benchmarks, per the ShadowPickle preprint that introduced it (arXiv:2607.17503).
SafeTensors safety property: the format stores tensor bytes plus a JSON header with no executable opcodes, so a load cannot run attacker code the way unpickling can (Hugging Face).
Key takeaways
A clean scan is a conditional negative, not a safety certificate. Model scanners work by disassembling a pickle and matching its imports and calls against a list of known-dangerous globals. A pass means "nothing on my list fired," which is a statement about the scanner, not about the model. Both the 2025 Sonatype CVEs and the 2026 ShadowPickle preprint exist because that gap is exploitable in practice.
The root cause is the format, not the tool. Pickle deserialization is a small virtual machine that can import modules and call functions while it rebuilds an object. That is a feature of pickle, so every pickle-format model is a potential code path. Patching PickleScan closes specific holes, but it cannot remove the execution primitive that lives inside the format itself.
Parser divergence is the quiet killer. Two of the 2025 bypasses work because the scanner's ZIP parser and PyTorch's ZIP parser disagree about the same file (NVD, CVE-2025-1944; NVD, CVE-2025-1945). Anywhere a security tool and a loader read a file differently, an attacker has room to make the tool see something benign while the loader sees something else.
SafeTensors changes the game because it removes the primitive. SafeTensors was built to store tensors safely, as an alternative to pickle, and it carries only weight data and a JSON metadata header (Hugging Face). There is no opcode stream to abuse, so a malicious "load-time" payload has nowhere to live. Migration is the highest-leverage control on this list.
Scanning is one layer, and it belongs inside defense in depth. The realistic posture is to prefer SafeTensors, verify provenance and signatures, sandbox every load of an untrusted artifact, allowlist sources, keep scanners layered and current, and have humans red team the ingestion pipeline end to end. No single control on that list is sufficient alone.
Methodology and sources
This analysis draws on four primary publishers, cited inline throughout and listed in full at the end:
Sonatype, Bypassing PickleScan (published March 11, 2025, by Trevor Madge). Vendor security research documenting four PickleScan bypass techniques and the corresponding CVEs. Sonatype is headquartered in the United States.
United States National Vulnerability Database (NVD), CVE records for CVE-2025-1716, CVE-2025-1889, CVE-2025-1944, and CVE-2025-1945 (published February and March 2025). The authoritative government catalog of vulnerability descriptions, CVSS scores, and CWE classifications.
ShadowPickle: Evading Machine Learning Model Scanners via Stealthy Pickle Deserialization Attacks (arXiv:2607.17503, submitted July 20, 2026, by Dhruv Pradhan, Sarang Nambiar, and Ezekiel Soremekun). A preprint. It has not completed peer review, so its figures are reported here as researcher claims and attributed to the specific attack variant they describe, not as settled findings.
Hugging Face SafeTensors documentation. The maintainer's own description of the format and its safety property.
The research cutoff for this post is July 2026. Where a figure could not be confirmed against one of these named primary sources, it was dropped rather than estimated. CVSS scores are reported from NVD's CVSS 3.1 base metrics; readers should note that scoring bodies can differ, and the numbering authority recorded lower CVSS 4.0 scores for several of these records, which is a normal artifact of two scoring systems rather than a contradiction. Evasion and difficulty figures from ShadowPickle are attributed to the named variant and benchmark, and the preprint status is stated wherever those numbers appear. This section lists sample scope and source provenance only.
Why loading a model can run code
The uncomfortable premise underneath this entire topic is simple. For the most common historical model formats, loading a model is not a passive read. It is program execution.
Pickle is a small virtual machine
Python's pickle module serializes objects into a compact byte stream and reconstructs them on load. That reconstruction is not a data copy. The pickle byte stream is a sequence of opcodes interpreted by a small stack-based virtual machine. Some of those opcodes import arbitrary modules and call arbitrary callables so that complex objects can rebuild themselves. An object can define what happens when it is unpickled, which means a crafted object can arrange for a function of the attacker's choosing to run the moment the file is loaded. This is a documented property of the format, not a bug. It is exactly why the Python documentation warns against unpickling data from untrusted sources.
Model weights for many popular frameworks were historically distributed as pickled objects, often inside a ZIP container, with extensions like .bin, .pt, .pth, .pkl, or .ckpt. When a loader deserializes one of those files, the pickle virtual machine runs. If the file was authored by an attacker, the attacker chose what runs.
Where the loader fits
PyTorch's torch.load is the canonical example. Loading a serialized model can trigger unpickling, and unpickling can execute code embedded in the archive. Recent PyTorch releases mitigate this by exposing a weights_only option that restricts loading to a safe allow list of tensor and container types, and by moving toward that safer behavior as the default (PyTorch, torch.load documentation). That control helps, but it depends on the loader, the version, and the calling code actually using it. Any pipeline that still deserializes untrusted pickle model files with the permissive path open is one crafted artifact away from code execution.
The practical takeaway for buyers: treat "load an untrusted model" as "run an untrusted binary." Every downstream control should follow from that framing.

What model scanners actually check
Because loading a pickle can run code, platforms and teams put a scanner in front of it. PickleScan is the widely used open-source example, described by its maintainers as a tool to scan Python pickle files for malicious content, and Hugging Face is among the platforms that rely on it inside their malware-scanning stack (Sonatype).
The mechanism is straightforward and inherently limited. A scanner disassembles the pickle opcode stream without executing it, extracts the module-and-function imports the pickle would perform, and compares them against a list of globals considered dangerous, such as calls that spawn processes or open network connections. If a flagged global appears, the file is marked suspicious. If none appears, the file passes.
That design has three structural weak points, and each one maps to a real 2025 bypass:
The list is a deny list, and deny lists are never complete. If a dangerous capability is reachable through a global that is not on the list, the scanner never flags it.
The scanner only inspects what it decides is in scope. If it only looks at files with expected extensions, an attacker can hide a pickle under an unexpected name.
The scanner has to parse the container, and its parser can disagree with the loader's parser. If the scanner reads the archive differently from the framework, the two can be shown different things.
A clean result, then, means "no listed global appeared in the parts I chose to parse the way I parse them." That is a useful signal. It is not a safety guarantee.
The 2025 PickleScan bypasses
In early 2025, Sonatype's security research turned each of those structural weak points into a concrete, cataloged vulnerability. The techniques below are described at a conceptual level only. The point is to show defenders why the failure modes are systemic, not to provide anything reusable.
CVE | Affected PickleScan | Weak point exploited | NVD CVSS 3.1 | CWE |
|---|---|---|---|---|
before 0.0.21 | Incomplete deny list | 9.8 critical | CWE-184 | |
before 0.0.22 | Out-of-scope file extension | 9.8 critical | CWE-646 | |
before 0.0.23 | Scanner crash via ZIP tampering | 6.5 medium | CWE-345 | |
before 0.0.23 | ZIP flag-bit manipulation | 9.8 critical | CWE-345 |
Table 1: Sonatype's four 2025 PickleScan bypass disclosures. Source: NVD CVE records and Sonatype, Bypassing PickleScan. CVSS scores are NVD CVSS 3.1 base metrics.
CVE-2025-1716: the incomplete deny list
Per NVD, versions of PickleScan before 0.0.21 did not treat pip as an unsafe global, so a crafted model could use pickle to pull in a malicious package from a public index during load (NVD). NVD scores it CVSS 3.1 9.8, critical, and classifies it as CWE-184, an incomplete list of disallowed inputs. This is the deny-list problem in its purest form. The dangerous capability was reachable through a global nobody had thought to block yet.
CVE-2025-1889: hiding outside the expected extension
Per NVD, versions before 0.0.22 only considered standard pickle file extensions in scope, so an attacker could include a malicious pickle under a non-standard extension and slip it past inspection (NVD). NVD scores it CVSS 3.1 9.8, critical, CWE-646, reliance on file name or extension. The scanner was not wrong about the files it looked at. It simply did not look everywhere the loader would.
CVE-2025-1944 and CVE-2025-1945: parser divergence
The last two are the most instructive because they do not attack the deny list at all. They attack the gap between two parsers. Per NVD, a ZIP archive manipulation can crash PickleScan while it tries to extract a PyTorch archive, yet PyTorch's more tolerant ZIP parsing still processes the file (NVD, CVE-2025-1944). Separately, modifying certain ZIP flag bits can make PickleScan fail to detect a malicious pickle inside the archive while torch.load still executes it (NVD, CVE-2025-1945). Both are classified CWE-345, insufficient verification of data authenticity. The lesson generalizes far beyond PickleScan: whenever a security tool and a loader interpret the same bytes differently, the difference is attack surface.
All four were fixed in PickleScan updates, so keeping the scanner current is genuinely worthwhile. But the pattern is what matters. Each fix closed one hole in a format whose fundamental behavior is to execute.
ShadowPickle: scanners still miss stealthy pickles in 2026
The 2025 CVEs might read as a one-time cleanup. The July 2026 ShadowPickle preprint suggests the underlying problem is durable.
ShadowPickle presents three stealthy pickle deserialization attacks that abuse the external module import mechanism of the pickle virtual machine to run payloads during deserialization while evading state-of-the-art scanners (arXiv:2607.17503). Across the study, the authors report that ShadowPickle evades ten state-of-the-art scanners and four model hubs. The headline result belongs to one specific variant: ShadowPickle "Overwritten" reaches a 63 percent evasion rate across scanners, up to 50 percent higher than existing attacks, per the abstract. The authors also release PickleBench, a dynamic benchmark for injecting these attacks into arbitrary benign models, which they report is up to 25.6 percent more challenging than three prior benchmarks.
Two caveats are load-bearing and stated deliberately. First, the 63 percent belongs to the "Overwritten" variant specifically, not to the technique family as a whole or to any single scanner. Second, arXiv:2607.17503 is a preprint. It has not completed peer review, so these figures should be read as a researcher claim that triangulates the 2025 CVE evidence, not as an independently validated benchmark. Even with those caveats, the direction is clear. More than a year after the PickleScan CVEs, independent researchers were still able to push a majority of scanners past a coin flip with a single variant. Static scanning of pickle formats is losing an arms race it was never structured to win, because the defender has to enumerate every dangerous path while the attacker only needs one the deny list missed.
The case for SafeTensors
If the problem is that the format executes, the durable fix is a format that does not.
SafeTensors is described by Hugging Face as a simple format for storing tensors safely, as opposed to pickle, while staying fast through zero-copy loading (Hugging Face). The security property is structural. A SafeTensors file is a JSON header describing tensor names, dtypes, and shapes, followed by the raw tensor bytes. There is no opcode stream, no import mechanism, and no callable to invoke during a load. Reading a SafeTensors file deserializes numbers, not behavior. A malicious load-time payload has nowhere to live because the format has no place to put executable instructions.
That is why migrating from pickle formats to SafeTensors is the single highest-leverage control a team can adopt. It does not patch a scanner. It retires the primitive the scanner was trying to catch. SafeTensors is already the default for a large share of models on major hubs and is used across widely deployed libraries, which makes the migration path unusually smooth compared to most security hardening.
A few honest caveats keep this from being a silver bullet:
SafeTensors protects the load, not everything around it. It removes arbitrary code execution at deserialization. It does not vouch for the weights themselves, which could still be backdoored or poisoned through training-time manipulation. Provenance and evaluation controls still matter.
Conversion has to be trustworthy. Converting a pickle model to SafeTensors typically requires loading the pickle first. Do that conversion in an isolated, sandboxed environment, never on a workstation or a shared build node with real access.
Coverage is not universal. Some artifacts, custom pipelines, and older checkpoints still ship as pickle. Where you cannot avoid pickle, every other layer below has to carry more weight.
A model-provenance control checklist
Treat this as a defense-in-depth checklist for any pipeline that ingests third-party models. No single item is sufficient. Together they turn a single point of failure into a layered system.

Prefer SafeTensors, and refuse pickle formats where you can. Make SafeTensors the required format for ingested models. Where a source only offers pickle, convert in isolation or reject it. This is the control that removes the execution primitive rather than filtering it.
Verify provenance and integrity, and sign what you promote. Pin models to a specific revision by commit hash rather than a floating tag. Verify checksums on download. Prefer publishers you can attribute, and apply cryptographic signing so that a promoted model in your registry is verifiably the artifact you reviewed, not a later substitution.
Sandbox every load of an untrusted artifact. Load and convert unknown models only in an isolated environment with least privilege, no standing credentials, and restricted network egress. If a load does try to execute, it should hit a wall, not your build system or a data-bearing host.
Allowlist sources and gate the pull. Do not let arbitrary hub pulls happen inside CI or production. Maintain an allowlist of approved publishers and models, mirror approved artifacts into an internal registry, and block direct external fetches from build and runtime paths.
Keep scanners layered and current, without trusting any one of them. Run scanning as one signal, update it promptly given how fast the PickleScan CVEs moved, and prefer more than one engine. Treat a clean result as "no known signature fired," never as a release gate on its own.
Red team the ingestion pipeline end to end. Have skilled humans probe how a crafted or substituted model would actually move through your intake, conversion, storage, and serving path. Scanners test files. Red teaming tests the system that trusts those files.
What this means for defenders
The through line from the 2025 CVEs to the 2026 preprint is that static model scanning is a control, not a guarantee, and buyers who treat a green checkmark as a safety certificate are trusting the wrong signal. Here is how that translates into decisions.
Rewrite your model-ingestion policy around SafeTensors. Make it the default and the requirement, and treat any pickle-format ingestion as an exception that needs sandboxing and sign-off. This is a policy change more than a spend, and it delivers the biggest risk reduction on this page.
Instrument provenance before you instrument detection. Signing, revision pinning, checksums, and an internal registry stop substitution attacks that no scanner can catch, because those attacks swap the artifact, not its contents.
Fund human testing of the pipeline, not just the file. The evasion research is a standing reminder that a scanner-only posture ages badly. Human-led AI red teaming of the model-ingestion path, the conversion steps, and the serving layer is where these systemic gaps surface. At Stingrai, model-format and ingestion-pipeline testing is human-pentester scope. Our autonomous agent, Snipe, is purpose-built for web application penetration testing, where it hunts complex web vulnerabilities like IDOR, business logic, and broken authorization. Assessing how a malicious model traverses an ML pipeline is deliberately kept with our senior human testers through our red teaming and broader offensive security services.
Use the results as compliance evidence. Documented red teaming and control validation of your model supply chain supports your SOC 2 and ISO 27001 programs by providing evidence that your AI ingestion risks are tested and managed. Stingrai is a CREST-accredited penetration testing service provider at the firm level, and our reports are written to slot into that evidence trail.
If you are building or defending an AI pipeline, the adjacent Stingrai deep dives on RAG vector store access control testing, MCP server security assessment, red teaming LLM and agentic apps, the OWASP Agentic AI Top 10 test-coverage checklist, and AI pentest data-handling due diligence round out the model supply-chain picture.
Frequently asked questions
If a Hugging Face model passes the platform security scanner, is it safe to load in production?
Not necessarily. A clean scanner result means no known-bad signature matched in that scanner version, not that the model is benign. Pickle-format models execute code during deserialization, and researchers have repeatedly bypassed the scanners platforms rely on, including four PickleScan CVEs disclosed by Sonatype in 2025 (Sonatype) and the 2026 ShadowPickle preprint. Treat scanning as one layer, prefer SafeTensors, and sandbox untrusted loads.
Why can loading a machine learning model run code at all?
Because many model formats are Python pickle objects, and unpickling runs a small virtual machine that can import modules and call functions while it rebuilds an object. A crafted model can arrange for attacker-chosen code to run the moment it is loaded. That is a documented property of pickle, which is why loading an untrusted pickle model is equivalent to running an untrusted program.
What is the difference between pickle and SafeTensors?
Pickle is a general Python serialization format whose deserialization can execute code, so a malicious pickle model can run a payload on load. SafeTensors is a format built to store tensors safely, carrying only a JSON header plus raw tensor bytes with no executable opcodes (Hugging Face). Reading a SafeTensors file deserializes numbers, not behavior, so a load cannot run attacker code the way unpickling can.
What were the 2025 PickleScan bypasses?
Sonatype disclosed four: CVE-2025-1716, an incomplete deny list that let a model reach a package installer; CVE-2025-1889, scanning only standard file extensions; CVE-2025-1944, a ZIP manipulation that crashes the scanner while PyTorch still loads the file; and CVE-2025-1945, ZIP flag-bit manipulation that hides a pickle from the scanner while torch.load executes it (NVD, CVE-2025-1945). NVD scores three of the four at CVSS 3.1 9.8, critical.
How severe was CVE-2025-1716?
NVD assigns CVE-2025-1716 a CVSS 3.1 base score of 9.8, critical, classified as CWE-184, an incomplete list of disallowed inputs (NVD). Versions of PickleScan before 0.0.21 did not treat the pip global as unsafe, so a crafted model could pull in a malicious package during loading.
What is ShadowPickle and how much does it evade scanners?
ShadowPickle is a July 2026 arXiv preprint presenting three stealthy pickle deserialization attacks and a benchmark called PickleBench. Its best-performing variant, "Overwritten," reaches a 63 percent evasion rate across ten scanners, up to 50 percent higher than existing attacks, per the abstract (arXiv:2607.17503). It is a non-peer-reviewed preprint, so the figure is attributed to that specific variant and read as a researcher claim rather than a settled result.
Does keeping PickleScan updated make my pipeline safe?
Updating helps and is worth doing, because the 2025 fixes closed real holes and the CVEs moved quickly. It does not make a pipeline safe on its own. Scanning is a deny-list approach against a format that executes, so it will always trail novel bypasses. The durable fix is to prefer SafeTensors and to wrap loading in provenance checks, sandboxing, and source allowlisting.
How do I migrate from pickle models to SafeTensors safely?
Convert in an isolated, sandboxed environment, because conversion usually requires loading the original pickle first, which is the risky step. Verify the source and checksum before conversion, perform the conversion with restricted privileges and no network egress, then store and serve only the resulting SafeTensors artifact. After migration, require SafeTensors for future ingestion and treat any remaining pickle sources as exceptions.
Does Stingrai use its AI agent to test model pipelines?
No. Stingrai's autonomous agent, Snipe, is purpose-built for web application penetration testing, where it hunts complex vulnerabilities such as IDOR, business logic flaws, and broken authorization. Model-format and ML ingestion-pipeline testing is deliberately kept with senior human pentesters through our red teaming and offensive security services, because it requires reasoning about how a crafted artifact traverses a bespoke pipeline.
References
Sonatype. Bypassing PickleScan: Sonatype Discovers Four Vulnerabilities. March 11, 2025. https://www.sonatype.com/blog/bypassing-picklescan-sonatype-discovers-four-vulnerabilities. Vendor security research documenting four PickleScan bypass techniques and their CVEs, and noting that model hubs rely on PickleScan in their malware-scanning stacks.
United States National Vulnerability Database. CVE-2025-1716. February 26, 2025. https://nvd.nist.gov/vuln/detail/CVE-2025-1716. PickleScan before 0.0.21 does not treat
pipas an unsafe global. CVSS 3.1 9.8, critical, CWE-184.United States National Vulnerability Database. CVE-2025-1889. March 3, 2025. https://nvd.nist.gov/vuln/detail/CVE-2025-1889. PickleScan before 0.0.22 only scans standard pickle file extensions. CVSS 3.1 9.8, critical, CWE-646.
United States National Vulnerability Database. CVE-2025-1944. March 10, 2025. https://nvd.nist.gov/vuln/detail/CVE-2025-1944. PickleScan before 0.0.23 can be crashed by ZIP archive manipulation while PyTorch still loads the file. CVSS 3.1 6.5, medium, CWE-345.
United States National Vulnerability Database. CVE-2025-1945. March 10, 2025. https://nvd.nist.gov/vuln/detail/CVE-2025-1945. PickleScan before 0.0.23 fails to detect malicious pickles when certain ZIP flag bits are modified. CVSS 3.1 9.8, critical, CWE-345.
Pradhan, Dhruv, Sarang Nambiar, and Ezekiel Soremekun. ShadowPickle: Evading Machine Learning Model Scanners via Stealthy Pickle Deserialization Attacks. arXiv preprint arXiv:2607.17503. Submitted July 20, 2026. https://arxiv.org/abs/2607.17503. Non-peer-reviewed preprint reporting three stealthy pickle attacks, the PickleBench benchmark, and a 63 percent evasion rate for the "Overwritten" variant across ten scanners.
Hugging Face. SafeTensors documentation. https://huggingface.co/docs/safetensors/index. Maintainer documentation describing SafeTensors as a format for storing tensors safely, as opposed to pickle, with zero-copy loading.
PyTorch. torch.load documentation. https://docs.pytorch.org/docs/stable/generated/torch.load.html. Documents the
weights_onlyoption that restricts unpickling to a safe allow list and the move toward safer default loading behavior.


