ML CVEs
Cracked mauve isometric cube split open to a glowing orange core, encircled by a ring of orange traffic cones on a dark navy grid platform.
Vulnerability Tracking

PyTorch Security: CVEs and Model Loading Hardening

PyTorch's most consequential CVEs cluster on one thing: loading a model file that runs code. A walk through the verified entries and how to harden.

By ML CVEs Editorial · · Updated · 12 min read

CVE-2025-32434 is a critical remote code execution flaw in PyTorch’s torch.load: on PyTorch 2.5.1 and earlier, a crafted model file can run code even when loaded with weights_only=True. NVD scores it 9.8 and the fix is PyTorch 2.6.0. A later bug in the same loader, CVE-2026-24747, raises the safe floor to 2.10.0.

If you look at PyTorch’s most serious CVEs in order, a single shape repeats: loading data — usually a model checkpoint — causes code to run. The framework’s numerical core is mature and rarely the source of a critical entry; the dangerous surface is the I/O boundary where bytes you did not produce get turned back into Python objects. Every one of the CVEs below is verified against the NVD record before it is cited here, and the pattern across them is more instructive than any single score.

PyTorch CVEs at a glance

Scores and affected ranges come from each NVD record (CVSS v3.1). The last row has no CVE and only GitHub’s severity label.

IDComponentAffectedFixed inScoreImpact
CVE-2025-32434torch.load with weights_only=True2.5.1 and earlier2.6.09.8Code execution on load
CVE-2026-24747weights_only unpicklerBefore 2.10.02.10.08.8Memory corruption, possible code execution
CVE-2024-48063 (disputed)RemoteModule in torch.distributed.rpc2.4.1 and earlierNo fix listed9.8Deserialization RCE over RPC
CVE-2022-45907torch.jit.annotations.parse_type_lineBefore 1.13.11.13.19.8Code execution via eval
CVE-2024-31580runtime/vararg_functions.cppBefore 2.2.02.2.04.0Heap overflow, denial of service
CVE-2025-3136CUDA caching allocator2.6.0Not listed3.3Local memory corruption
GHSA-g6v3-crfc-cggjFlatBuffers parsing in torch::loadBefore 2.1.02.1.0ModerateAccess to an arbitrary address

A CVE-only feed misses that last row: PyTorch published GHSA-g6v3-crfc-cggj in September 2025 without a CVE ID. Watch the project’s advisory page too, as ML model CVE tracking recommends.

CVE-2025-32434: torch.load RCE even with the “safe” flag

CVE-2025-32434 is the one to internalize. NVD records it as a remote command execution vulnerability in PyTorch when loading a model using torch.load — and critically, it applied even with weights_only=True, on versions 2.5.1 and prior. CVSS base score 9.8 (critical). The fix is PyTorch 2.6.0, which also makes weights_only=True the default.

GitHub, as the CVE numbering authority, scores the same flaw 9.3 on CVSS v4.0, and both records classify it as CWE-502, deserialization of untrusted data. PyTorch published its advisory, GHSA-53q9-r3pm-6pq6, on April 17, 2025, and NVD published the CVE the next day. The GitHub Advisory Database entry showed an EPSS probability of 2.187% (82nd percentile) when checked in October 2026, and the PyPA advisory database tracks it as PYSEC-2025-41.

The reason this matters beyond its score: for years the standard mitigation advice was “pass weights_only=True and you’re safe.” This CVE proved that guidance was a flag on top of a fundamentally unsafe loader, and a parser bug was enough to defeat it. If your runbook still says “we set weights_only, we’re fine,” that runbook had an expiry date and CVE-2025-32434 was it.

How the bypass worked

Ji’an Zhou and Lishuo Song of Alibaba Cloud found the flaw and presented the research at DEF CON 33 in August 2025. Their abstract names the root finding: torch.load with weights_only=True still supported TorchScript, and the TorchScript engine gave them a path to RCE. The patch the advisory links, commit 8d4b8a9, makes torch.load raise a RuntimeError when weights_only=True meets a checkpoint saved in the legacy .tar format. If an old pipeline starts failing with that error after the upgrade, the fix is working; do not turn the flag off to silence it.

There is no patched 2.5.x line. PyTorch’s security policy states that security fixes are only applied to the current release and are never backported.

The downstream trap: vLLM pinned the vulnerable torch

The flag gave false comfort to projects that had done the right thing. vLLM fixed its own pickle bug, CVE-2025-24357, in 0.7.0 by passing weights_only=True to torch.load in its Hugging Face weight iterator (GHSA-rh4j-5rhw-hr54). Its April 22, 2025 follow-up, GHSA-ggpf-24jw-3fcw, explains why that was not enough: vLLM’s requirements pinned PyTorch 2.5.1, so a default install pulled in a torch vulnerable to CVE-2025-32434. Every vLLM release before 0.8.0 was affected, and 0.8.0 moved to PyTorch 2.6.0.

Your exposure is set by the torch version the resolver installed, including pins inside other packages. The advisory’s attack scenario, a victim fetching a malicious pretrained repository, is the route covered in Hugging Face model supply chain risk.

The sequel: the safe unpickler itself

CVE-2026-24747 is the same lesson taught twice. NVD records a flaw in the weights_only unpickler that lets a crafted .pth checkpoint corrupt memory, and potentially reach arbitrary code execution, when it is loaded with torch.load(..., weights_only=True). CVSS base score 8.8 (high), CWE-502 and CWE-94, affecting every release prior to 2.10.0 and fixed in 2.10.0.

PyTorch published the advisory on January 26, 2026. Its serialization notes now say plainly that weights_only=True does not guard against denial of service and that memory corruption may still be possible during loading.

Read the two together and the conclusion is not “the flag is broken” but “the flag is a parser, and parsers have bugs.” weights_only=True genuinely removes the __reduce__ payload path that makes a plain pickle an execution primitive, and it is still the right default. It just is not a trust boundary you can put an untrusted checkpoint on the other side of and stop thinking.

The original eval-in-the-loader bug

CVE-2022-45907 (CVSS 9.8) is older and narrower but worth knowing as the archetype: in PyTorch before the trunk fix (NVD lists every version before 1.13.1 as affected), torch.jit.annotations.parse_type_line could cause arbitrary code execution because eval was used unsafely. A type annotation string flowing into eval is the same class of mistake as a serialization opcode that calls a function — code execution arising from data that was supposed to be inert. Different code path, identical lesson.

Distributed RPC: powerful by design, dangerous by default

CVE-2024-48063 records that in PyTorch <= 2.4.1, the RemoteModule has a deserialization RCE (CVSS 9.8). One honest caveat: this entry is disputed — multiple parties argue it describes intended behavior of the distributed framework rather than a flaw, since torch.distributed.rpc is explicitly documented as trusting its peers. That dispute is itself the takeaway. PyTorch’s RPC layer assumes a trusted network. If you expose it to anything you do not fully control, you have handed out code execution, CVE or no CVE. Treat the RPC port like an unauthenticated shell and network-isolate it.

Not everything is RCE — and the score reflects that

CVE-2024-31580 is a heap buffer overflow in /runtime/vararg_functions.cpp in PyTorch before 2.2.0, scored 4.0 (medium). It is a real memory-safety bug, but its modest score and local-leaning vector are an antidote to treating “PyTorch CVE” as automatically code-red. A buffer overflow reachable only when you feed a crafted model through a specific runtime path is a very different exposure than an unauthenticated load that runs a shell command. Read the affected component before you panic-patch.

Worth tracking even at low score

CVE-2025-3136 reports memory corruption in torch.cuda.memory.caching_allocator_delete (c10/cuda/CUDACachingAllocator.cpp) in PyTorch 2.6.0, scored only 3.3 on CVSS v3.1. It is included here precisely because it is minor: it shows the same recent PyTorch version (2.6.0) that fixed the critical load bug still carries low-severity issues. Currency is not a one-time event. You upgrade to escape 32434 and you inherit a new, smaller backlog — which is normal and fine, as long as you keep tracking.

Am I affected by CVE-2025-32434? Five checks

You are affected if any environment runs torch below 2.6.0 and calls torch.load on files you did not produce, whether you pinned that version or a dependency did. Below 2.10.0 you are still exposed to CVE-2026-24747, the sibling bug in the same loader. Check every image and lockfile, then work through these steps:

  1. Inventory every environment. Run pip-audit inside each environment that loads models, or pip-audit -r ./requirements.txt against a requirements file. It queries PyPI’s vulnerability data by default, and -s osv switches to OSV. Include container images and notebook kernels, not only the service repository.
  2. Upgrade past both floors. Anything below 2.6.0 is exposed to CVE-2025-32434 and anything below 2.10.0 to CVE-2026-24747. The newest release on PyPI is torch 2.14.1, published September 30, 2026. Confirm that no dependency pins torch back down.
  3. Find every torch.load call. Flag calls that pass weights_only=False or a custom pickle_module. Setting TORCH_FORCE_WEIGHTS_ONLY_LOAD=1 forces weights_only=True on every call, including third-party code you cannot edit; TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD=1 in a deployment config does the opposite and should be removed.
  4. Allowlist instead of switching the flag off. When a checkpoint fails to load, torch.serialization.get_unsafe_globals_in_checkpoint(f) lists the globals that are not allowlisted without running them. Add only the ones you trust with torch.serialization.add_safe_globals or the scoped safe_globals context manager. The docs warn that this static check can miss types built dynamically during unpickling.
  5. Assume compromise where it fits. If a vulnerable host loaded a checkpoint from an untrusted source, treat it as a host that ran unknown code. The triage workflow covers scoping that.

What PyTorch’s own security policy does not cover

PyTorch’s security policy narrows what counts as a vulnerability, and the gaps land on the user. It excludes crashes from invalid arguments, denial of service through resource consumption, attacks that need local filesystem write access, and malformed objects returned by a weights_only load. Two consequences follow:

  • Only the current release gets fixes. Running a few minor versions behind means carrying known bugs with no upstream patch path.
  • Sandboxing is your job. The policy says to run untrusted models in an isolated environment such as a sandbox, and that “TorchScript models should be treated the same way as locally executable code from an unknown source.” Distributed checkpoints are likewise assumed trusted, so loading one can execute code.

Reports go through the GitHub advisory form, and the policy commits to publishing or dismissing each within 90 days.

The hardening that actually holds

The CVEs above are not independent surprises; they are repeated confirmations of one exposure — we deserialize artifacts we did not produce. Hardening therefore targets the exposure, not each entry:

  • Change the format, not the flag. Prefer safetensors for weights. It is a header plus raw tensor bytes with no callable invocation on load, so it removes the code-execution sink rather than guarding it. This is the single highest-leverage change, and it is what defangs the entire 32434 lineage. Model file format security compares pickle, .keras, GGUF, ONNX and safetensors on exactly this axis.
  • Stay on a current PyTorch. 2.6.0 both fixes CVE-2025-32434 and makes weights_only=True the default, but the current patched floor is 2.10.0, not 2.6.0: CVE-2026-24747 reaches memory corruption through the weights_only unpickler in every release before 2.10.0. Because fixes are not backported, track the current release (2.14.1 as of October 2026). Upgrading is the fix; a flag was never the fix.
  • Scan artifacts before they reach the loader. Hugging Face runs scanning on the Hub; picklescan and Trail of Bits’ fickling can flag dangerous opcodes in CI before a file ever touches torch.load. Note that scanners have their own gaps, so treat scanning as defense in depth, not a guarantee. Which one to run, and what a clean result is worth, is set out in static and dynamic ML scanners and in the checkpoint-specific model-file detection workflow. The broader set of model-scanning and provenance tools covers the signing and registry half of the same control.
  • Isolate the RPC layer. If you use torch.distributed.rpc, the CVE-2024-48063 dispute is your warning label: it trusts peers by design. Keep it on a private network segment with no untrusted reachability. The same assumption produced 10.0-scored entries in vLLM’s ZeroMQ transport and llama.cpp’s RPC backend, catalogued in inference server CVEs.
  • Pin and verify provenance. Pull checkpoints by digest, record the hash that was scanned, and reject anything that does not match at load time.

How to read the next PyTorch CVE

When the next entry lands, do not start from the CVSS number. Start from one question: does this code path touch bytes I did not produce and verify? A 9.8 in torch.load is an emergency if you load community checkpoints at runtime and nearly inert if every artifact is built in-house from trusted source and stored content-addressed. A 4.0 buffer overflow can be more urgent than a 9.8 for a team whose architecture happens to reach the vulnerable path with attacker-influenced input. The score is computed against a generic threat model; your deployment is the real one.

To see which of these entries apply to the exact torch version you run, alongside the rest of your stack filtered by severity and fix availability, use the ML stack CVE filter and paste in a requirements.txt.

See also

FAQ

is weights_only=true safe in pytorch

Safer, not safe. On PyTorch 2.6.0 and later it is the default and blocks the classic pickle __reduce__ payload, but CVE-2025-32434 bypassed it before 2.6.0 and CVE-2026-24747 corrupted memory through it before 2.10.0. PyTorch’s own docs say it does not stop denial of service and memory corruption may still occur.

what is the difference between cve-2025-32434 and cve-2026-24747

Both break torch.load with weights_only=True, but in different ways. CVE-2025-32434 (9.8, fixed in 2.6.0) was a bypass reaching code execution on 2.5.1 and earlier. CVE-2026-24747 (8.8, fixed in 2.10.0) is memory corruption inside the weights_only unpickler itself, with possible code execution, and its vector requires user interaction. Only 2.10.0 or later clears both.

does cve-2025-32434 affect safetensors files

No. CVE-2025-32434 lives in torch.load, which parses pickle-based checkpoints such as .pt, .pth and .bin files. Safetensors stores a header plus raw tensor bytes and is read without unpickling, and PyTorch’s security policy rates it the safest loading option, though the least flexible. Converting weights removes this entire CVE class.

does pytorch backport security fixes to older versions

No. PyTorch’s security policy states that security fixes are only applied to the current release and never backported. The CVE-2025-32434 fix exists from 2.6.0 onward and the CVE-2026-24747 fix from 2.10.0 onward. Distribution packages are a separate track: NVD links a Debian LTS notice for the first and a Red Hat erratum for the second.

what is the latest secure version of pytorch

As of October 2026 the newest release on PyPI is torch 2.14.1, published September 30, 2026. Any release from 2.10.0 onward clears both CVE-2025-32434 and CVE-2026-24747, but because PyTorch fixes only the current release, staying on the latest minor version is the only way to receive future upstream security fixes.

Sources

  1. CVE-2025-32434: torch.load RCE despite weights_only=True — NVD
  2. CVE-2026-24747: memory corruption in the weights_only unpickler, fixed in 2.10.0 (PyTorch advisory)
  3. PyTorch 2.6 release notes: torch.load weights_only default change
  4. CVE-2022-45907: torch.jit.annotations unsafe eval RCE — NVD
  5. CVE-2024-48063: PyTorch RemoteModule deserialization RCE — NVD
  6. CVE-2024-31580: PyTorch heap buffer overflow — NVD
  7. Model serialization security and safetensors — Hugging Face
  8. CVE-2025-3136: memory corruption in the PyTorch CUDA caching allocator — NVD
  9. GHSA-53q9-r3pm-6pq6: torch.load with weights_only=True RCE (PyTorch advisory)
  10. GHSA-53q9-r3pm-6pq6 in the GitHub Advisory Database (CVSS v4, EPSS, PYSEC-2025-41)
  11. PyTorch commit 8d4b8a9: Prevent legacy_load when weights_only=True
  12. Safe Harbor or Hostile Waters: the TorchScript engine in PyTorch (DEF CON 33 talk)
  13. vLLM GHSA-ggpf-24jw-3fcw: CVE-2025-24357 fix bypass with PyTorch < 2.6.0
  14. vLLM GHSA-rh4j-5rhw-hr54: malicious model to RCE by torch.load (CVE-2025-24357)
  15. PyTorch security policy
  16. PyTorch security advisories (GitHub)
  17. GHSA-g6v3-crfc-cggj: arbitrary address access while parsing flatbuffer format (PyTorch advisory)
  18. PyTorch serialization semantics: weights_only, safe globals and environment variables (2.14 docs)
  19. torch on PyPI (2.14.1, released September 30, 2026)
  20. pip-audit: audit Python environments for known vulnerabilities
Subscribe

ML CVEs — in your inbox

CVEs in ML libraries, frameworks, and the AI/ML supply chain. Sent only when there is something worth sending.

No spam. Unsubscribe anytime.

Related