# Arm NN TFLite DetectionPostProcess malformed FlexBuffer PoC This repository demonstrates a load-time heap-buffer-overflow read in Arm NN's TFLite parser. A verifier-valid `.tflite` model can provide a one-byte `custom_options` vector for the `TFLite_Detection_PostProcess` custom operator. Arm NN passes that vector directly to `flexbuffers::GetRoot(...).AsMap()` without first validating the FlexBuffer. ## Tested version - Arm NN commit: `2b61cecc9df7a43fca1463795062cf359e6be820` - Commit date: 2026-07-02 - Parser library: `libarmnnTfLiteParser.24.7.dylib` - FlatBuffers compiler: 24.3.25 - Instrumentation: Clang AddressSanitizer and UndefinedBehaviorSanitizer ## Root cause `src/armnnTfLiteParser/TfLiteParser.cpp` copies attacker-controlled custom options and parses them without a FlexBuffers verifier: ```cpp auto custom_options = operatorPtr->custom_options; const flexbuffers::Map& m = flexbuffers::GetRoot(custom_options.data(), custom_options.size()).AsMap(); ``` `flexbuffers::GetRoot` reads the root byte-width and packed type from the end of the supplied buffer. A one-byte vector has no room for both values, so the first access reads one byte before the allocation. The outer TFLite FlatBuffer is valid. The TFLite verifier checks the `custom_options` vector as a byte vector but does not validate its nested FlexBuffer encoding. ## Differential fixtures - `control.tflite` contains the upstream test's valid DetectionPostProcess FlexBuffer and loads successfully. - `trigger.tflite` is the same model structure with `custom_options` reduced to the single byte `0x00`. SHA-256: ```text b1828036d5ace9f157f1a1b34a0ad94614989d8b227f127f146af5c3e332e704 control.tflite af9c5e86ab6973b87eb78ad17573f79739e01dcf7e17e0d50348ce95a82a185f trigger.tflite ``` ## Reproduction Build Arm NN's TFLite parser with ASan/UBSan, then run: ```bash ./reproduce.sh ``` Expected control result: ```text loaded 1280 bytes ``` Expected trigger result: ```text ERROR: AddressSanitizer: heap-buffer-overflow READ of size 1 ... in armnnTfLiteParser::TfLiteParserImpl::ParseDetectionPostProcess 0x... is located 1 bytes before 1-byte region ``` The included `repeated-results.txt` records three independent runs. Every control exited `0`; every trigger exited `134` with the same ASan signature. ## Impact Any service, model inspection pipeline, or application that imports an attacker-supplied TFLite DetectionPostProcess model through Arm NN can be terminated during model loading. The invalid nested encoding reaches native out-of-bounds memory access before inference. This PoC demonstrates denial of service through a native out-of-bounds read. It does not claim code execution or data disclosure. ## Suggested remediation Validate `custom_options` with the FlexBuffers verifier before calling `GetRoot`, and reject buffers that are too short to contain a root reference. The parser should also validate that the root is a map and that required keys have the expected scalar types before reading descriptor fields. ## Research safety The fixtures are synthetic and operate only on a local instrumented build. No hosted service or third-party system is contacted.