YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
onnx-tensorrt ConvTranspose output_shape negative-index OOB read (PoC)
Status: verified against live main HEAD as of 2026-07-06
(commit 7c51a63a719180eb5160c874c111746f3fb46a6b, dated 2026-06-22).
Summary
onnx/onnx-tensorrt's ConvTranspose importer accepts an ONNX
output_shape INTS attribute of any length (including zero/empty)
because OnnxAttrs::get<nvinfer1::Dims>() (OnnxAttrs.cpp:85-97) only
enforces an upper bound (nbDims > MAX_DIMS) and never a lower
bound. The result is passed unchecked into generatePadding()
(importerUtils.cpp:655-680), which computes
outputOffset = outputShape.nbDims - nbSpatialDims;
...
outputShape.d[outputOffset + i] // importerUtils.cpp:667
If the attacker supplies an output_shape shorter than the op's
spatial rank (e.g. [] on a standard 4D/NCHW 2D ConvTranspose, where
nbSpatialDims = rank(input) - 2 = 2), outputOffset goes negative
(0 - 2 = -2) and the loop reads outputShape.d[-2] / d[-1] --
an out-of-bounds read on the fixed int64_t d[8] member of the
stack-allocated nvinfer1::Dims object.
- CWE-125 (Out-of-bounds Read)
- Attacker input: the
output_shapeattribute of aConvTransposenode inside a crafted.onnxmodel file (noauto_padset, orauto_pad == "NOTSET", which is the default). - Impact: undefined behavior / crash (info-leak-adjacent OOB stack
read) when TensorRT's
nvonnxparserparses an attacker-supplied ONNX model. CVSS ~4.0 (Low), consistent with other input-validation OOB-read findings in this parser.
Why a full build was not possible in this environment
onnx-tensorrt's CMakeLists.txt requires:
- NVIDIA's proprietary TensorRT 11.1 SDK (
NvInfer.h+libnvinfer.so) - CUDA toolkit (
cuda_runtime_api.h,nvcc)
Neither the proprietary TensorRT runtime library nor a CUDA toolkit is
available in this research environment, and TensorRT itself is
closed-source (only its C++ headers are mirrored publicly under
NVIDIA/TensorRT on GitHub). A full nvonnxparser build driven by an
actual ONNX model file is therefore not achievable here.
What this PoC does instead
Rather than fabricate or simulate the bug, this PoC:
- Copies the two vulnerable functions verbatim, character for
character, from the live onnx-tensorrt source at the commit above:
OnnxAttrs::get<nvinfer1::Dims>()body (OnnxAttrs.cpp:88-96)generatePadding()in full (importerUtils.cpp:655-680)makeDims()helper in full (importerUtils.cpp:1448-1454), used by the real ConvTranspose importer to build the other Dims arguments (kernelSize,strides,dilations,begPadding,endPadding,outputPadding)
- Reconstructs
nvinfer1::Dims/nvinfer1::Dims64andnvinfer1::PaddingModeverbatim from NVIDIA's public TensorRT-OSS headers (NVIDIA/TensorRT,release/11.1branch -- the version onnx-tensorrt's own README pins), isolated from the rest of the header tree only to avoid an unrelated CUDA-toolkit dependency. No TensorRT runtime library is linked or required --Dimsis a plain POD struct andgeneratePadding()performs no TensorRT API calls. - Drives these real functions with the exact attacker-controlled
value an empty
output_shape = []INTS attribute would produce after ONNX protobuf parsing (std::vector<int32_t>{}), feeding it through the same call sequence the real ConvTranspose importer uses at onnxOpImporters.cpp:1258 and :1262-1263, for a realistic 4D (NCHW) ConvTranspose input. - Compiles with
clang++ -fsanitize=address,undefinedand captures the real crash.
Files:
nvinfer_min.hpp-- minimal verbatim TensorRT type defs (see header comment for exact upstream line provenance)harness.cpp-- verbatim vulnerable functions + drivermain()(see header comment for exact upstream line provenance)full_asan_evidence.log-- build command, source commit hash, run command, and complete AddressSanitizer outputasan_run.log-- raw ASan output only
Build & run
clang++ -std=c++17 -O0 -g -fsanitize=address,undefined \
-fno-omit-frame-pointer -fno-sanitize-recover=address \
-I. harness.cpp -o harness_asan
./harness_asan
Result
AddressSanitizer deterministically reports a stack-buffer-underflow
(reported by ASan under its generic "stack-buffer-overflow" banner,
with the shadow-memory report explicitly stating the access
"underflows" the outputShape variable) at the exact line
corresponding to outputShape.d[outputOffset + i]:
==NNNNNN==ERROR: AddressSanitizer: stack-buffer-overflow on address ...
READ of size 8 at ... thread T0
#0 ... in generatePadding(...) harness.cpp:113:62
#1 ... in main harness.cpp:170:5
...
Address ... is located in stack of thread T0 at offset 136 in frame
#0 ... in generatePadding(...) harness.cpp:104
This frame has 6 object(s):
[32, 104) 'inputShape.byval'
[144, 216) 'outputShape.byval' <== Memory access at offset 136 underflows this variable
...
See full_asan_evidence.log for the complete, unedited trace.
Dedup note
This is distinct from the 5 onnx-tensorrt findings already filed by this researcher:
- external_data path traversal
volume()integer overflowparseExternalWeightsnumeric-offset OOB- GRU/RNN activations iterator OOB
SplitconvertAxisOOB write
Root cause here is a negative array index derived from an
unvalidated attribute length in generatePadding(), not a weight
offset, integer overflow, or iterator misuse -- a different function,
different trigger, different code path.