ONNX Runtime TensorScatter String Double-Free PoC
This repository contains a minimal defensive proof of concept for a native
memory-safety issue in ONNX Runtime's CPU implementation of standard
TensorScatter-24.
The affected kernel registers all tensor types, including tensor(string),
but copies std::string object storage with memcpy. Long strings therefore
produce aliased heap ownership and a double free during ordinary model loading
and constant folding.
This PoC is provided for coordinated vulnerability reporting through Huntr's Model File Vulnerability program. Run it only in an isolated local environment. It contains no code-execution payload, persistence, network activity, or custom operator.
Tested Target
- ONNX Runtime: official Linux x64 CPU release
v1.27.1 - Release archive SHA-256:
25b1ef1fea1acd210d63f8f24dc870ad6e077795ce1f54876252c6d3803c15af - Current affected main revision:
361184e61957410f19153754f325806972546d5b - Affected source:
onnxruntime/core/providers/cpu/llm/tensorscatter.cc
The complete affected source file is byte-identical between the tested release and the listed main revision.
Included Files
string_embedded_candidate.onnx: checker-valid, self-contained 592-byte candidate using only embedded initializers and standardTensorScatter-24.float_control.onnx: structurally matched numeric control.build_models.py: deterministic generator usingonnx==1.22.0.tensorscatter_runner.cc: public ONNX Runtime C++ API reproducer.SHA256SUMS: hashes for every PoC artifact.
The candidate has no graph inputs. It embeds two 96-byte cache strings, one 96-byte update string, and one integer write index. The long strings exceed small-string optimization on the tested standard library.
Reproduction
Download and verify the official ONNX Runtime release:
curl -LO https://github.com/microsoft/onnxruntime/releases/download/v1.27.1/onnxruntime-linux-x64-1.27.1.tgz
echo "25b1ef1fea1acd210d63f8f24dc870ad6e077795ce1f54876252c6d3803c15af onnxruntime-linux-x64-1.27.1.tgz" | sha256sum -c -
tar -xzf onnxruntime-linux-x64-1.27.1.tgz
Compile the runner:
g++ -std=c++17 -O0 -g \
tensorscatter_runner.cc \
-Ionnxruntime-linux-x64-1.27.1/include \
-Lonnxruntime-linux-x64-1.27.1/lib \
-lonnxruntime \
-o tensorscatter_runner
Run the matched control:
LD_LIBRARY_PATH=onnxruntime-linux-x64-1.27.1/lib \
./tensorscatter_runner float float_control.onnx
Expected output and exit status:
control_output=99,22
exit=0
Run the self-contained candidate:
MALLOC_CHECK_=3 \
LD_LIBRARY_PATH=onnxruntime-linux-x64-1.27.1/lib \
./tensorscatter_runner embedded string_embedded_candidate.onnx
Observed result in three of three fresh isolated processes:
TensorScatter: in-place optimization not activated, copying past_cache to present_cache (64 bytes)
free(): double free detected in tcache 2
exit=134
The runner does not reach its post-session output print. The failure occurs
during the public Ort::Session constructor with default SessionOptions.
Independent Memory-Safety Evidence
Preloading the system AddressSanitizer runtime against the unchanged official
library reports an attempted double free on a 97-byte allocation. The initial
allocation, first free, and second free are all attributed to the official
libonnxruntime.so.1; the stack reaches Ort::Session::Session(...).
The tested library build ID is
c28e051f3eb5995a651f0cea9ad35b7f25d6ba6d.
Security Impact
An application that loads an attacker-supplied ONNX model using the ordinary CPU provider can be terminated during session construction. The demonstrated impact is heap ownership corruption, double free, and deterministic denial of service.
This report does not claim code execution, arbitrary-address write, confidentiality loss, GPU impact, or scanner bypass.
Suggested Remediation
Use string-aware assignment for the initial cache copy and both update paths
when the element type is string. Retain memcpy only for trivially copyable
fixed-size types. Alternatively, restrict CPU registration if string
TensorScatter is not intended to be supported.
Regression tests should cover long and short strings, out-of-place and in-place planning, linear and circular modes, default constant folding, direct inference, and a numeric control.