ONNX ParseData heap OOB-write β security-research PoC artifact
β οΈ SECURITY RESEARCH ARTIFACT β DO NOT LOAD THESE FILES OUTSIDE AN ISOLATED, INTENTIONAL TEST ENVIRONMENT. These
.onnxfiles are intentionally malformed to demonstrate a memory-corruption bug. They are not machine-learning models, contain no useful weights, and must never be loaded by a production or shared service.
This repository hosts the malicious model artifacts for a coordinated, authorized vulnerability disclosure submitted through the huntr Model File Vulnerability (MFV) program against onnx/onnx.
What this is
A heap out-of-bounds write (CWE-787) in onnx/defs/tensor_util.cc ParseData<T>(). The function sizes its destination vector with res.resize(raw_data_size / sizeof(T)) (integer division floors) and then memcpys the full raw_data_size bytes. When raw_data length is not an exact multiple of sizeof(T), the copy writes up to sizeof(T) - 1 attacker-controlled bytes past the heap allocation.
The path is reachable from onnx.checker.check_model() β the standard untrusted-model validation API β via sparse-tensor INT64 index validation (check_sparse_tensor_indices β ParseData<int64_t>).
Files
| File | What it triggers |
|---|---|
evil15.onnx |
Sparse initializer with an INT64 indices tensor, dims=[1], 15-byte raw_data (15 % 8 = 7). check_model() runs the 15-byte memcpy into an 8-byte buffer β 7-byte heap OOB write, then proceeds into the post-parse index-range check (proving the copy executed). |
evil_silent.onnx |
Same structure; first 8 bytes are a valid in-range index and the 7 trailing bytes are the overflow payload β check_model() returns success while the heap is already corrupted (silent corruption). |
Both files are ~115 bytes. Under a stock pip wheel the 7-byte overflow may not visibly crash (no ASAN, allocator slack); an AddressSanitizer build makes the OOB write deterministic. See the huntr report for the ASAN harness and full write-up.
Reproduce (isolated environment only)
from huggingface_hub import hf_hub_download
import onnx # onnx==1.22.0
p = hf_hub_download("Ano1X8/onnx-parsedata-oob-poc", "evil_silent.onnx", repo_type="model")
m = onnx.load(p)
onnx.checker.check_model(m) # reaches ParseData<int64_t> and memcpy's 15 bytes into an 8-byte buffer
Responsible use
Published solely to give the huntr triage team a reproducible artifact for coordinated disclosure. Do not redeploy, repackage, or load these files against any system you do not own and intend to test. Reporter: Ano1X8 (@ano1x8).