| tags: | |
| - security | |
| - proof-of-concept | |
| # Tensorizer header_len unbounded allocation DoS PoC | |
| This repository contains a minimal proof-of-concept file for responsible disclosure through Huntr. | |
| **Summary:** A 73-byte tensorizer-format file declares the first tensor header's length (`header_len`, an unsigned 64-bit field read directly from the file) as `2**40` (1 TiB). `tensorizer.serialization._TensorHeaderDeserializer.from_io` allocates `bytearray(header_len)` immediately after reading this value, with no upper bound and no check against the actual remaining bytes in the file/stream. This causes an immediate large memory allocation attempt before any tensor data, or even the tensor-selection/skip logic, is reached. | |
| **Files:** | |
| - `minimal_tensorizer_header_len_dos.tensors`: 73-byte crafted PoC file. | |
| - `generate_tensorizer_poc.py`: script that generates the PoC file using only Python's stdlib `struct` module (no dependency on the `tensorizer` package itself), matching the exact binary layout verified against `tensorizer/serialization.py` (`_FileHeader.from_io`, `_TensorHeaderDeserializer.from_io`). | |
| **Reproduction:** | |
| Run with a timeout and/or memory limit, since a successful trigger means a large allocation attempt, not a clean completion: | |
| ``` | |
| timeout 5s python3 -c "from tensorizer import TensorDeserializer; TensorDeserializer('minimal_tensorizer_header_len_dos.tensors')" | |
| ``` | |
| **Expected behavior:** The deserializer should reject the file immediately because the declared header length is implausible (either exceeds a sane maximum, or doesn't fit in the remaining stream). | |
| **Actual behavior:** The process attempts to allocate a `bytearray` of the declared size (1 TiB in this PoC, but any value up to `2**64-1` is accepted) before any validation. | |
| This PoC is availability-only. It does not execute code, access external services, or include secrets. | |