Almost every serious vulnerability in the model-distribution supply chain reduces to the same root cause: a deserialization routine that executes code while it is reconstructing an object. It is CWE-502, it has been understood for decades, and it keeps producing ML CVEs because the serialization format the ecosystem standardized on was never safe to point at untrusted data — and the entire model-sharing culture is built on pointing it at untrusted data.
Why the default serialization primitive is the wrong one for model files
The Python documentation states the problem plainly: the relevant module is not secure, and you should only deserialize data you trust. Deserialization here is not a parser; it is a small stack-based virtual machine. The scanners that try to inspect that machine are compared in malicious model file detection. A REDUCE opcode calls a callable with arguments taken from the byte stream, and a malicious object’s reduction method can return something equivalent to (os.system, ("command",)). Loading such a file runs the command. No memory corruption, no exploit chain — the format does exactly what it was designed to do.
PyTorch’s default .pt/.pth checkpoints, older joblib and scikit-learn artifacts, and many community model dumps use this format under the hood. When a practitioner downloads a checkpoint from a random repository and calls torch.load(path), they are running whatever the producer embedded in it. Trail of Bits demonstrated full weaponization of this in 2021, including payloads that survive re-serialization, and the technique has not aged.
The CVEs keep arriving — even after the “fix”
The instructive recent example is CVE-2025-32434. PyTorch had long recommended torch.load(..., weights_only=True) as the safe path, and a great deal of guidance treated that flag as the mitigation. CVE-2025-32434 showed that on PyTorch prior to 2.6.0, weights_only=True could still be bypassed to achieve remote code execution. The control everyone was told to rely on did not fully hold; the real fix was an upgrade plus making weights_only=True the default in 2.6.0.
This is the pattern worth internalizing: a deserialization mitigation that is merely a flag on a fundamentally unsafe loader is one parser bug away from failing, and the CVE that proves it tends to arrive years after the advice solidified. The same shape recurs across the ecosystem. Keras .h5/SavedModel files have carried code-execution issues through Lambda layers and deserialized configs, and the current record for that framework is in TensorFlow and Keras security vulnerabilities. numpy.load with allow_pickle=True is a CWE-502 sink and was the basis of CVE-2019-6446. Each is independently scored, each gets its own NVD entry, and a defender tracking only “PyTorch CVEs” or only “numpy CVEs” sees fragments of one structural problem. Our PyTorch security writeup covers that framework’s share of the pattern.
Reading these CVEs correctly
A deserialization CVE in an ML library should be triaged against one question: does my pipeline ever load a model artifact whose bytes I did not produce and verify? If the answer is yes — fine-tuning community checkpoints, loading user-uploaded models, pulling from a public hub at runtime — the practical severity is closer to unauthenticated RCE on the inference host than whatever generic CVSS vector the entry carries. If every artifact is built in-house from trusted source and stored in an integrity-checked registry, the same CVE may be largely inert for you. The score will not tell you which case you are in; your architecture does.
What actually mitigates it
- Change the format, not the flag. Prefer
safetensorsfor weights. It is a non-executable format: a header plus raw tensor bytes, with no callable invocation during load. This removes the sink rather than guarding it. How every common format compares on this point — and where the risk moves once the payload is inert — is set out in model file format security. - Treat model files as untrusted code by default. Scan artifacts before loading. Hugging Face runs scanning on the Hub and surfaces results;
picklescanandfickling(Trail of Bits) can flag dangerous opcodes in CI before a file ever reachestorch.load. Which one to run, and what a green result is worth against a prepared adversary, is compared in ML vulnerability scanner software; the signing and registry controls around the scan are in AI supply-chain security tools. - Pin and verify provenance. Pull models by digest, not floating tags. Record the hash that was scanned and reject anything that does not match at load time. Content-addressed registry storage makes “did these bytes change” answerable. Record the result somewhere queryable: an AI bill of materials inventory turns “are we affected” into a lookup, and the model SBOM fields define what each entry has to carry.
- Sandbox the loader. If you must load legacy artifacts in the unsafe format, do it in a locked-down, network-isolated process with a minimal filesystem view, so a
REDUCEpayload lands somewhere disposable. - Keep loaders current and re-test assumptions. CVE-2025-32434 is the reminder that “we set
weights_only=True” is a claim with an expiry date. Track the loader’s CVEs specifically and upgrade, rather than trusting a flag whose guarantees a future parser bug can revoke.
The deserialization CVE is not going away, because the incentive that created it — frictionless model sharing — is not going away. The defenders who handle it well stop treating each entry as a new surprise and start treating “we deserialize artifacts we did not produce” as a standing exposure that the next CVE merely re-confirms. The runtime-glue half of the same supply chain is covered in trust_remote_code and the ML orchestration CVE class, and the serving layer that loads these artifacts has its own record in inference server CVEs. Upstream of both, the ML pipeline supply-chain attack path shows how a hostile artifact reaches the loader in the first place.
See also
- ML CVE database: what’s tracked and missing
- ML stack CVE filter — check your packages and versions
- More on this subject: model security, pickle and supply chain coverage