Downloads · 30 days
6
15% of all-time downloads
EnigmaConsultant/huntr-poc-tflite-weightspace-backdoor
huntr-poc-tflite-weightspace-backdoor is a machine learning model from EnigmaConsultant. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
A .tflite FlatBuffer image classifier that:
Downloads · 30 days
6
15% of all-time downloads
All-time downloads
41
Public
Repo size
12.8 MB
Likes
0
Public
Click a slice to open those files.
.npy12.6 MB · 98%
From the Hugging Face model README
tf.lite.Interpreter, invisible to modelscanA .tflite FlatBuffer image classifier that:
tf.lite.Interpreter(model_path=...) API — no custom
ops, no pickle, no code execution, no external delegate.0).modelscan==0.8.8 (the file is skipped entirely — the
scanner has no analyzer for the TFLite FlatBuffer format).The backdoor lives entirely in the learned convolution/dense weights (classic BadNets data-poisoning). There is nothing structural, no code, and no custom operator for a static scanner to flag.
tflitetf.lite.Interpreter — the documented, standard TFLite runtime entry pointTraining side (build_backdoor.py, tf-keras, MNIST, 3 epochs):
[keras] clean_acc = 0.9854 attack_success = 0.9970
[tflite] wrote model.tflite (230404 bytes)
Victim side — loaded ONLY with tf.lite.Interpreter and run for inference
(victim_load.py):
benign_accuracy_clean = 0.9790 # normal accuracy on 2000 clean test images
target_class = 0
clean_nontarget_to_tgt = 0.0005 # baseline: clean non-'0' inputs landing on '0'
triggered_flip_rate = 0.9978 # attack success: non-'0' inputs + trigger -> '0'
Benign behaviour is normal (97.9% top-1). The trigger flips 99.78% of non-target inputs to the attacker class, versus a 0.05% baseline — a clean, unambiguous backdoor.
model.tflite sha256: 82384f98d38b6b64cdc9937353d74911d89ea8b1bc7f7e7e90d716e5c849717c
--- Summary ---
No issues found! 🎉
--- Skipped ---
Total skipped: 1
The following file .../model.tflite was skipped during a ModelScan scan:
Model Scan did not scan file
modelscan 0.8.8 has no analyzer for the .tflite FlatBuffer format, so it
skips the file and returns a clean verdict. A user relying on modelscan as a
supply-chain gate receives no warning while shipping a fully backdoored model.
Full output in scan_results.txt.
TFLite is the dominant on-device / edge inference format (Android ML Kit, Coral, embedded, mobile apps). Models are routinely pulled from Hugging Face, model zoos, and third-party vendors and dropped straight into an app. Because:
.tflite
at all,an attacker can publish a backdoored classifier that passes scanning, benchmarks normally, and yet is fully attacker-controlled whenever the physical/logical trigger is present (e.g. a sticker patch on a camera frame, a crafted request). This yields authentication bypass, content-filter evasion, misclassification of attacker assets, etc., depending on the deployment.
Weight-space / output-manipulation backdoors have been filed for: onnx,
tf-savedmodel, safetensors, gguf, keras_native, pytorch-statedict, torchscript,
circle, nemo, coreml, executorch, pmml, mleap, dl4j, flax (openvino in
progress). tflite is not in that set. This finding is the TFLite
FlatBuffer runtime (tf.lite.Interpreter), a distinct format, loader, and
serialized container (FlatBuffer, not protobuf/pickle/HDF5/msgpack), with its
own modelscan skip-path. It is not reducible to any filed format.
Circle (.circle, the Samsung ONE runtime) and TFLite share the same
underlying FlatBuffer schema — Circle is a superset fork of the TFLite
schema. This finding is nonetheless distinct on every dimension huntr scores:
tflite ("TFLite (.tflite) –
Google") and circle as separate selectable Model File Format targets; a
report is filed against one format value.tf.lite.Interpreter (TensorFlow 2.21.0), the documented TFLite runtime. The
Circle finding loads through the Samsung ONE circle runtime. Neither model
is interchangeable at the loader level..tflite
emitted by tf.lite.TFLiteConverter.from_keras_model, with the TFLite file
identifier, consumed by the TFLite interpreter — not a .circle file..tflite on its
own (no analyzer registered for the extension/format); this is verified
end-to-end below, independent of the Circle result.Shared schema lineage does not collapse the two: the vulnerable object, the loader that materializes the backdoor, the format string filed, and the scanner skip decision are all TFLite-specific.
.tflite is unscanned rather than folding it into a silent "No issues found",
or (b) add TFLite FlatBuffer analysis (op-set / subgraph inspection cannot
detect weight backdoors, so weight backdoors additionally need provenance,
signing, and trigger/robustness testing)..tflite models.python3.12 -m venv venv
./venv/bin/pip install tensorflow-cpu tf-keras scipy numpy "modelscan==0.8.8"
# 1. train the BadNets backdoor and emit the standard FlatBuffer
TF_USE_LEGACY_KERAS=1 ./venv/bin/python build_backdoor.py
# 2. load ONLY via tf.lite.Interpreter and measure benign vs triggered
./venv/bin/python victim_load.py
# 3. confirm modelscan says clean / skips the file
./venv/bin/modelscan -p model.tflite --show-skipped
build_backdoor.py — trains the poisoned model, converts with
tf.lite.TFLiteConverter, writes model.tflite + eval arrays.victim_load.py — loads with tf.lite.Interpreter only, reports benign
accuracy and trigger flip-rate.model.tflite — the backdoored artifact (standard FlatBuffer).clean_inputs.npy, clean_labels.npy — 2000 clean MNIST eval images + labels.triggered_inputs.npy — same 2000 images with the 3×3 corner trigger applied.scan_results.txt — exact modelscan 0.8.8 output + tooling versions.(venv/ was deleted after verification to save disk; recreate with the commands above.)