# Risk map — pytorch/pytorch

> Canonical page: https://codevetter.com/unpack/pytorch/risk-map

# Risk map — pytorch/pytorch

Scanned commit 5711f1a4586cb0a3dbb3d67538df814db48f94f4 (2026-09-22). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The dominant risks are deserialization and the trust boundary of model artifacts: torch.load is a pickle surface (mitigated by the now-default weights_only mode), TorchScript/mobile artifacts are executable code, and distributed primitives have zero authentication or encryption by design. The project's own SECURITY.md explicitly scopes out crashes/OOB from invalid inputs and cache poisoning, meaning large parts of the C++ kernel surface are intentionally unhardened. Internally, torch/__init__.py is a fragile monolith with import-order constraints and environment mutation (PATH, dlopen flags), serialization depends on vendored miniz internals, and the sprawling CI matrix plus content-hashed Docker images create operational blast radius.
- torch.load with weights_only=False executes arbitrary pickle — documented as 'Never load data from an untrusted source'; weights_only=True became the default in 2.6 and uses the restricted _weights_only_unpickler with a safe-globals allowlist. — [torch/serialization.py#L77-91](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/torch/serialization.py#L77-L91) [torch/serialization.py#L1334-1337](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/torch/serialization.py#L1334-L1337) [SECURITY.md#L49](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/SECURITY.md#L49)
- torch.distributed primitives (c10d, RPC, TCPStore) include no authorization and send unencrypted messages: 'anybody with access to the network can execute arbitrary code with the privileges of the user running PyTorch.' — [SECURITY.md#L85-89](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/SECURITY.md#L85-L89)
- Distributed checkpoints intentionally bypass weights_only protections — loading a checkpoint 'may execute arbitrary code'; the trust model assumes your own store produced the artifact. — [SECURITY.md#L89](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/SECURITY.md#L89)
- TorchScript and mobile .ptl models are treated as untrusted executable code; even inspection tools like torch.utils.model_dump can execute embedded code. — [SECURITY.md#L59-63](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/SECURITY.md#L59-L63)
- PyTorch's stated policy is to not validate all inputs: wrong shapes/dtypes/devices can cause crashes or out-of-bounds memory access and are classified as bugs, not vulnerabilities — a deliberate, large unhardened C++ surface. — [SECURITY.md#L23-37](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/SECURITY.md#L23-L37)
- Local caches (compiled kernels, Triton cache) are trusted by design; cache poisoning is explicitly out of scope, so any code path writing/reading these caches assumes a non-hostile filesystem. — [SECURITY.md#L35](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/SECURITY.md#L35)
- CI supply-chain mitigations are documented: sccache caching is susceptible to corruption (artifacts must not run near secrets), non-ephemeral runners risk reverse shells (hence no repo secrets), and release builds require ephemeral runners + cold-start builds + deployment environments. — [SECURITY.md#L104-116](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/SECURITY.md#L104-L116)
- torch/__init__.py is a 3588-line module with hard ordering constraints (device modules must precede multiprocessing; quantized/ao imports must be last), global mutation (sys.setdlopenflags, os.environ['PATH'] on Windows, os.add_dll_directory), and a sorted-__all__ runtime assertion — edits here have global blast radius. — [torch/__init__.py#L466-505](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/torch/__init__.py#L466-L505) [torch/__init__.py#L2715-2765](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/torch/__init__.py#L2715-L2765) [torch/__init__.py#L306-309](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/torch/__init__.py#L306-L309)
- _load's fast path hardcodes miniz internals — data descriptor sizes 24/16 bytes, 0xFFFFFFFF boundary, header-offset arithmetic that 'must be kept in sync with that of miniz' — coupling the Python loader to vendored zip-writer behavior. — [torch/serialization.py#L2065-2116](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/torch/serialization.py#L2065-L2116)
- Windows loading mutates process-global state: prepends dll_paths to os.environ['PATH'] and LoadLibraryW's every *.dll in torch/lib — classic DLL search-order/preload surface. — [torch/__init__.py#L290-320](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/torch/__init__.py#L290-L320)
- Generated-file traps: .pyi stubs are generated from .pyi.in templates (edit the template, not the output), and torchgen emits the ATen/op registration surface at build time — editing generated files or native_functions.yaml without understanding codegen silently changes public API. — [AGENTS.md](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/AGENTS.md) [aten/src/ATen/native/README.md#L16-27](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/aten/src/ATen/native/README.md#L16-L27)
- The .ci/docker directory is content-hashed: any file change — including the README — forces a full Docker image rebuild for CI; AGENTS.md warns against touching it (e.g., during upstream Ubuntu outages). — [AGENTS.md](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/AGENTS.md)
- sparse-tensor validation under weights_only is an O(nnz) scan per tensor — a documented performance cliff for large checkpoints that can look like a hang. — [torch/serialization.py#L1380-1384](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/torch/serialization.py#L1380-L1384)
- Test selection depends on downloaded configs and target determination (options.enable_td runs 25% of tests), so a TD/config failure can silently reduce coverage; failures in the gating workflows (job-filter, llm-td) cascade into what actually runs. (inferred) — [test/run_test.py#L2336-2339](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/test/run_test.py#L2336-L2339) [test/run_test.py#L2383-2388](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/test/run_test.py#L2383-L2388) [.github/workflows/trunk.yml#L44-60](https://github.com/pytorch/pytorch/blob/5711f1a4586cb0a3dbb3d67538df814db48f94f4/.github/workflows/trunk.yml#L44-L60)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
