OpenVINO IR reader β stack-exhaustion DoS PoC (read_model)
β οΈ This repo contains a malicious proof-of-concept model file for a security report. It is NOT a usable ML model. Do not load userdata_50000.xml on a machine you care about β it deliberately crashes the OpenVINO loader.
What it is
Two malicious IR files, each triggering an independent unbounded-recursion site in the IR deserializer (same missing-depth-cap class). Both have no .bin (weights are not needed).
userdata_50000.xml(1.84 MB) β aParameterwhose<rt_info>nests<user_data>50 000 deep βset_custom_rt_inforecursion.nested_ti_10000.xml(7.98 MB) βTensorIteratorlayers nested 10 000 deep via<body>βparse_functionrecursion.
When OpenVINO parses either file, the deserializer recurses once per nesting level with no depth limit, exhausting the stack and crashing read_model with SIGSEGV.
Reproduce (one line each)
pip install openvino # tested on 2026.2.1
python -c "import openvino as ov; ov.Core().read_model('userdata_50000.xml')" # -> Segfault (8/8)
python -c "import openvino as ov; ov.Core().read_model('nested_ti_10000.xml')" # -> Segfault (3/3)
Symbolized AddressSanitizer traces: asan-stackoverflow-evidence.txt (Site A), asan-parse_function-evidence.txt (Site B).
Root cause
Unbounded recursion in the IR deserializer, src/core/xml_util/src/xml_deserialize_util.cpp:
set_custom_rt_info(lines 134β153) β recurses per nested<user_data>element.parse_function(line 921; recursion at line 871) β recurses per nested subgraph body (TensorIterator/Loop/If), a second instance of the same missing-guard class.
Symbolized AddressSanitizer trace (from-source Debug build, HEAD ce20c09):
==ERROR: AddressSanitizer: stack-overflow
#21 set_custom_rt_info src/core/xml_util/src/xml_deserialize_util.cpp:147
#22 set_custom_rt_info src/core/xml_util/src/xml_deserialize_util.cpp:147
... (thousands of identical frames) ...
Regenerate the PoC
fe_recursion.py β gen_user_data(50000) (the .xml here) and gen_nested_ti(20000) (the subgraph-body variant).
Impact
Availability DoS: any service that calls read_model/compile_model on an untrusted OpenVINO IR model can be crashed by one small (~1.8 MB) .xml.
Fix
Cap recursion depth (or use an explicit worklist) in set_custom_rt_info and parse_function; reject IR whose rt_info/subgraph nesting exceeds a sane bound.