Downloads · 30 days
9
30% of all-time downloads
character-s/openvino-tflite-output-count-oob-poc
openvino-tflite-output-count-oob-poc is a machine learning model from character-s. Use it for the machine learning task on the model card, and read the license before you ship it in a product. The card lists the license as apache-2.0.
This repository contains a minimal control/malicious pair for a load-time heap out-of-bounds read in OpenVINO's TensorFlow Lite frontend. It is intended for coordinated vulnerability disclosure and defensive regressio…
Downloads · 30 days
9
30% of all-time downloads
All-time downloads
30
Public
Repo size
628 B
Likes
0
Public
Click a slice to open those files.
.md17.8 KB · 39%
From the Hugging Face model README
This repository contains a minimal control/malicious pair for a load-time heap out-of-bounds read in OpenVINO's TensorFlow Lite frontend. It is intended for coordinated vulnerability disclosure and defensive regression testing.
Do not run the malicious model inside a production process. The demonstrated impact is deterministic process termination while loading the model.
An attacker-controlled TFLite operator can declare more outputs than the OpenVINO translator actually returns. The common TFLite conversion loop records the model-declared output count, replaces its pre-sized output vector with the translator's shorter return vector, and then indexes the shorter vector using the original count.
The supplied model declares two outputs for a unary ABS operator. The ABS
translator returns one ov::Output<ov::Node>, but the common loop reads
ov_outputs[1]. ASAN reports an 8-byte heap out-of-bounds read immediately after
a 24-byte allocation.
No inference is required. Both public filename APIs reach the bug:
ov.Core().read_model(path)ov.Core().compile_model(path, "CPU")| OpenVINO build | Control | Malicious |
|---|---|---|
2026.2.1-21919-ede283a88e3-releases/2026/2 | read/compile succeed | read/compile terminate with SIGSEGV |
2024.1.0-15008-f4afc983258-releases/2024/1 | read/compile succeed | read/compile terminate with SIGSEGV |
source d04123f36df4fcf2f4c17efd002b55d1941f41c3 with ASAN+UBSAN | succeeds | heap-buffer-overflow READ8 |
compile_model casesRelWithDebInfo with Clang 18, ASAN, and UBSANThe package-local regeneration and reproduction checks are recorded in
evidence/package-validation.txt.
models/
control_abs_1_output.tflite
malicious_abs_2_outputs.tflite
scripts/
gen_tflite_output_arity.py
inspect_tflite_arity.py
repro_read_model.py
repro_compile_model.py
patches/
fix-tflite-output-count.patch
evidence/
asan-current-head.txt
duplicate-preflight.md
model-structure.txt
package-validation.txt
patch-validation.txt
release-matrix.txt
HUNTR_REPORT.md
LICENSE
requirements.txt
SHA256SUMS
| Model | Size | SHA-256 | ABS operator outputs |
|---|---|---|---|
models/control_abs_1_output.tflite | 312 bytes | 0956c42f20709fb799bcd4ba5ceb7e5423fee28d886d45ad9b4a36b548a68b9a | [1] |
models/malicious_abs_2_outputs.tflite | 316 bytes | f9ef16c95dd7671b0f3c187fe3e8a103c306a7f4843ece40ba2e3a064478de63 | [1, 2] |
Both models contain the same model version, subgraph, three scalar FLOAT32
tensors, graph input [0], graph output [1], and ABS opcode. Tensor index 2
exists and is in range. The only semantic difference is the operator output
vector.
The following commands were tested with Python 3.12 on Linux.
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
Inspect the pair:
python scripts/inspect_tflite_arity.py \
models/control_abs_1_output.tflite \
models/malicious_abs_2_outputs.tflite
Expected relevant output:
models/control_abs_1_output.tflite: 312 bytes
version=3 subgraphs=1 tensors=3
graph_inputs=[0]
graph_outputs=[1]
builtin_opcode=101
operator_inputs=[0]
operator_outputs=[1]
models/malicious_abs_2_outputs.tflite: 316 bytes
version=3 subgraphs=1 tensors=3
graph_inputs=[0]
graph_outputs=[1]
builtin_opcode=101
operator_inputs=[0]
operator_outputs=[1, 2]
Run each command in a separate process because the malicious model terminates the interpreter in affected releases:
python scripts/repro_read_model.py models/control_abs_1_output.tflite
python scripts/repro_read_model.py models/malicious_abs_2_outputs.tflite
python scripts/repro_compile_model.py models/control_abs_1_output.tflite CPU
python scripts/repro_compile_model.py models/malicious_abs_2_outputs.tflite CPU
Expected Linux results on OpenVINO 2026.2.1 and 2024.1.0:
control read_model: success, exit 0
malicious read_model: SIGSEGV, exit 139
control compile_model: success, exit 0
malicious compile_model: SIGSEGV, exit 139
The models can be regenerated deterministically:
python scripts/gen_tflite_output_arity.py
sha256sum -c SHA256SUMS
Current source location:
src/frontends/tensorflow_lite/src/frontend.cpp:218-240
Simplified vulnerable sequence:
const auto& out_size = decoder->get_output_size();
ov::OutputVector ov_outputs(out_size);
ov_outputs = (*op_fun)(node_context);
for (size_t i = 0; i < out_size; ++i) {
const auto& name = decoder->get_output_tensor_name(i);
all_tensor_values[name] = ov_outputs[i];
}
For the malicious model:
decoder->get_output_size() returns 2 from the serialized operator.ov::OutputVector of size 1.out_size == 2 and reads
ov_outputs[1].The invalid ov::Output is copied through its internal std::shared_ptr, which
causes a release-build crash. See evidence/asan-current-head.txt for the
sanitized ASAN excerpt.
A small attacker-supplied model causes native memory to be read immediately outside an OpenVINO-owned heap allocation during ordinary model loading. This can terminate tools or services that load untrusted TFLite files.
The demonstrated impact is availability loss only. This repository does not claim remote code execution, information disclosure, arbitrary memory access, or arbitrary write.
Primary weakness: CWE-125, Out-of-bounds Read.
Validate the translator postcondition before the common loop indexes its return vector:
FRONT_END_GENERAL_CHECK(ov_outputs.size() == out_size,
"TFLite translator returned an unexpected number of outputs for ",
decoder->get_op_type(),
".");
The proposed patch is in patches/fix-tflite-output-count.patch. In an
ASAN+UBSAN build, it preserved successful loading of the control and changed the
malicious model into a controlled OpenVINO exception without a sanitizer error.
Removing the patch and rebuilding restored the READ8 report.
No exact public report for this translator output-count postcondition was found
during the final pre-submission search. The checked sources, queries, and
adjacent results are recorded in evidence/duplicate-preflight.md. A private
duplicate cannot be ruled out.
The affected component is OpenVINO's own TFLite frontend, not the upstream TensorFlow Lite interpreter or FlatBuffers library. The intended disclosure target is OpenVINO - Intel.