ONNX shape inference performed an out-of-bounds read when processing a malformed RNN, GRU, or LSTM node from opsets 1–6 whose first input had a rank other than three. RNNShapeInference_opset1_to_6() checked whether the input shape was present but accessed dim(0) and dim(1) without first checking its rank. A crafted model could therefore terminate a process that called onnx.shape_inference.infer_shapes(). The model passed onnx.checker.check_model() before reaching the vulnerable path.
ONNX ConvTranspose shape inference performed an out-of-bounds read when the weight tensor had fewer than three dimensions and the model did not provide a kernel_shape attribute. The inference function derived an empty effective_kernel_shape vector from the undersized weight tensor, then indexed that vector once for each spatial dimension of the input tensor. A crafted model passed onnx.checker.check_model() and caused SIGSEGV when passed to onnx.shape_inference.infer_shapes().
ONNX shape inference did not safely validate the required Scan num_scan_inputs attribute. Two malformed values could terminate or disrupt the process: If the attribute was missing, ctx.getAttribute("num_scan_inputs") returned null and was dereferenced. If the attribute was negative, conversion to size_t produced a very large value that reached a vector allocation and raised std::length_error. The negative-value variant passed onnx.checker.check_model() before reaching shape inference.
ONNX's Python tensor-materialization helpers could allocate memory according to attacker-controlled tensor dimensions without verifying that a packed sub-byte payload contained the declared number of elements. A very small model could therefore cause a disproportionately large allocation when an application called onnx.numpy_helper.to_array() or constructed onnx.reference.ReferenceEvaluator with the model. The issue affected UINT2, INT2, UINT4, INT4, and FLOAT4E2M1 tensors stored in either raw_data or packed int32_data.
Heap-buffer-overflow READ (16 bytes) in Gemm_7_6::adapt_gemm_7_6() (onnx/version_converter/adapters/gemm_7_6.h:41) when ConvertVersion() processes a model with a Gemm node whose input tensors have fewer than 2 dimensions. The adapter accesses B_shape[1] without checking rank. On Release builds the OOB read is silent; ASan confirms 16-byte read past a 48-byte allocation.
Null pointer dereference (SIGSEGV) in Upsample_6_7::adapt_upsample_6_7() (onnx/version_converter/adapters/upsample_6_7.h:31) when convert_version() processes a model with an Upsample node that has zero inputs. The adapter accesses node->inputs()[0]->sizes() without checking input count. 107-byte PoC crashes on Release build. This is the same class of bug as the Cast adapter advisory (separate report) but in a different adapter, different file, and different operator.
The save_external_data method seems to include multiple issues introducing a local TOCTOU vulnerability, an arbitrary file read/write on any system. It potentially includes a path validation bypass on Windows systems. Regarding the TOCTOU, an attacker seems to be able to overwrite victim's files via symlink following under the same privilege scope. The mentioned function can be found here: https://github.com/onnx/onnx/blob/main/onnx/external_data_helper.py#L188
The ExternalDataInfo class in ONNX was using Python’s setattr() function to load metadata (like file paths or data lengths) directly from an ONNX model file. The problem? It didn’t check if the "keys" in the file were valid. Because it blindly trusted the file, an attacker could craft a malicious model that overwrites internal object properties.
Summary Issue: Symlink traversal in external data loading allows reading files outside the model directory. Affected code: onnx/onnx/checker.cc: resolve_external_data_location used via Python onnx.external_data_helper.load_external_data_for_model. Impact: Arbitrary file read (confidentiality breach) when a model’s external data path resolves to a symlink targeting a file outside the model directory. Root Cause The function resolve_external_data_location(base_dir, location, tensor_name) intends to ensure that external data files reside within base_dir. It: Rejects empty/absolute paths Normalizes the relative …
The issue is in onnx.load — the code checks for symlinks to prevent path traversal, but completely misses hardlinks, which is the problem, since a hardlink looks exactly like a regular file on the filesystem.
A path traversal vulnerability via symlink allows to read arbitrary files outside model or user-provided directory.
Any pipeline using hub.load() with silent=True and an external repo string is silently loading whatever the repo owner ships. If that model executes arbitrary code on load, the attacker has access to the machine.