| # Coordinated-disclosure security PoC — PyTorch flatbuffer loader OOB read |
|
|
| **This is NOT a usable model.** It is a proof-of-concept malicious model file submitted under coordinated |
| disclosure to huntr (Model File Vulnerability program) for the PyTorch maintainers. Do not load it except |
| in an isolated, sanitizer-enabled environment. |
|
|
| ## What it demonstrates |
| `poc_attrs_attr_names.ptl` is a PyTorch flatbuffer (`.ptl`) model file. Loading it via |
| `torch.jit.jit_module_from_flatbuffer` / `torch._C._load_jit_module_from_bytes` / |
| `_load_for_mobile` triggers an **out-of-bounds heap read during model parse**, before any module code |
| runs, in `FlatbufferLoader::getOrCreateClassTypeForObject` (`flatbuffer_loader.cpp:639`). |
|
|
| Root cause: the loader iterates `i` over `Object.attrs` but indexes `ObjectType.attr_names` with the same |
| `i`. The two flatbuffer vectors are sized independently and the structural verifier never cross-checks their |
| lengths, so a file whose `attrs` is longer than its `attr_names` over-reads the names vector and then |
| dereferences the garbage offset as a `String*`. |
|
|
| ## Reproduce (isolated, sanitizer build) |
| With an ASan build of PyTorch: |
| ``` |
| ASAN_SO=$(gcc -print-file-name=libasan.so); STDCXX_SO=$(gcc -print-file-name=libstdc++.so) |
| LD_PRELOAD="$ASAN_SO:$STDCXX_SO" ASAN_OPTIONS=detect_leaks=0:halt_on_error=1:abort_on_error=1 \ |
| python -c "import torch; torch._C._load_jit_module_from_bytes(open('poc_attrs_attr_names.ptl','rb').read())" |
| ``` |
| Expected: `AddressSanitizer: heap-buffer-overflow READ` at `flatbuffer_loader.cpp:639`. The captured trace |
| is in `asan_trace.txt`. `reproduce.py` builds the artifact from scratch and triggers it. |
|
|
| ## Disclosure |
| Coordinated disclosure via huntr. Do not redistribute. Access is gated to the huntr triage bot only. |
|
|