| # onnx-tensorrt β OOB read via unvalidated external_data `offset` (CWE-125) |
| |
| Loading `malicious.onnx` with **onnx-tensorrt** (NVIDIA's TensorRT ONNX parser; also bundled in NVIDIA/TensorRT) |
| triggers an out-of-bounds read while importing the model's weights. |
| |
| ## Root cause |
| `onnx-tensorrt/WeightsContext.cpp`, `parseExternalWeights()`: the `offset` from a TensorProto's |
| `external_data` map is used directly as `weightsPtr = mmap_base + offset` with **no bounds check against the |
| mapped file size** (only `length` is validated, against the tensor's dims). `convertOnnxWeights()` then reads |
| the weights at `mmap_base + offset` (for `DOUBLE` tensors, via `convertDouble()` at parse time). |
| `offset` is fully attacker-controlled (a decimal string parsed with `atoll`), so the read address is attacker-controlled. |
|
|
| ## Files |
| - `poc.zip` β contains `malicious.onnx` (the model) + `w.bin`; unzip before running. The ONNX model whose single initializer `w` uses `external_data` with `offset=1073741824` (1 GiB), `dtype=DOUBLE`, `dims=[8]` |
| - `w.bin` β the (valid, 64-byte) external weights file it references |
| - `harness.cpp` / `stubs.cpp` / `build.sh` β a GPU-free ASAN harness that runs the real onnx-tensorrt weight-import path on `malicious.onnx` |
| - `PROOF.txt` β the AddressSanitizer report |
|
|
| ## Reproduce (GPU-free, ~minutes) |
| 1. `git clone https://github.com/onnx/onnx-tensorrt && git clone https://github.com/NVIDIA/TensorRT` (for `include/` headers) |
| 2. Get protobuf without sudo: `apt-get download protobuf-compiler libprotobuf-dev libprotobuf32t64 && for d in *.deb; do dpkg-deb -x "$d" localroot; done` |
| 3. Copy `onnx-ml.proto` (from the `onnx` pip package) into `onnx/`, then run `build.sh`. |
| 4. `unzip poc.zip && ./poc_oob malicious.onnx` β `AddressSanitizer: SEGV on ... READ` in `convertDouble` at `mmap_base + 0x40000000` (== the 1 GiB offset). |
|
|
| Alternatively, on a machine with TensorRT + a GPU: `trtexec --onnx=malicious.onnx` reaches the same import path. |
|
|
| ## Fix |
| In `parseExternalWeights`, validate `offset` (and `offset + length`) against the mapped file size before |
| `weightsPtr = mmap_base + offset`; reject negative/out-of-range offsets. |
|
|
| ## Not a duplicate of the known ONNX external_data CVEs |
| This bug is in **NVIDIA's `onnx-tensorrt` parser** (`WeightsContext.cpp`), a different codebase from the `onnx` |
| Python/C++ library. The publicly known ONNX external_data issues are **path traversal**: |
| - CVE-2022-25882 β onnx `<1.13` external_data path outside model dir |
| - CVE-2026-27489 β onnx `<1.21` external_data symlink escape |
|
|
| `onnx-tensorrt` already guards `../` path traversal. This report is a **different bug class** β an unvalidated |
| numeric **`offset`** (not a path) added to the mmap base β out-of-bounds **read**. No CVE/GHSA/OSV or prior huntr |
| report covers the onnx-tensorrt `offset` gap. |
|
|
| ## Severity |
| CVSS 3.1 `AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H` = 6.5 (Medium) for the demonstrated crash/DoS; the attacker-controlled |
| read address gives information-disclosure potential that could raise it. |
|
|