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.

TFLite NormalizationOptions Metadata Authority β€” PoC

Summary

This repository demonstrates that the TFLite Task Library (tflite-support) reads and applies NormalizationOptions mean/std values from a model's embedded FlatBuffer metadata at inference time for FLOAT32 inputs, without any validation or bounds checking. An adversarially crafted model with extreme mean/std values produces silently wrong output with no exception or warning.

Affected consumer: tflite_support.task.vision.ImageClassifier (Task Library)
Not affected: Raw tflite_support.Interpreter (does not apply NormalizationOptions)
Root: TensorMetadata.process_units[0].NormalizationOptions.{mean, std} FlatBuffer field
Runtime stage: Pre-inference (applied as (pixel - mean) / std before inference kernel)


Affected Consumer

The TFLite Task Library (tflite-support) ImageClassifier automatically reads NormalizationOptions from model metadata and applies normalization before inference:

from tflite_support.task import core, vision

opts = vision.ImageClassifierOptions(
    base_options=core.BaseOptions(file_name="model.tflite")
)
clf = vision.ImageClassifier.create_from_options(opts)
result = clf.classify(vision.TensorImage.create_from_array(image_array))

The normalization is applied transparently β€” the caller provides uint8 pixel data and the library applies (pixel - mean) / std per the embedded metadata before passing to the inference kernel. There is no API to disable or override this behavior for untrusted models.


Tested Environment

Item Value
OS x86_64 Linux (required β€” wheel not available for aarch64)
Python 3.10
tflite-support 0.4.4
TFLite delegate XNNPACK CPU
Base model float32, [1,224,224,3] β†’ GlobalAveragePooling2D β†’ Dense(3)

Files

File Description
reproduce_tflite_normalization_divergence.py Reproduction script β€” creates/loads models and demonstrates divergence
inspect_hash_matrix.py Hash matrix inspection and metadata diff verification
clean_model.tflite Benign model with NormalizationOptions mean=0.5, std=0.5
mutated_model.tflite Adversarial model with NormalizationOptions mean=200.0, std=0.001
requirements.txt Python dependencies
evidence_runtime_results.json Runtime test results (clean vs mutated)
evidence_reproducibility.json Reproducibility test results (5x same-process + 3x subprocess)
evidence_hash_matrix.json SHA256 hashes of all model artifacts
evidence_distinctness_matrix.json Distinctness analysis vs prior TFLite findings
SHA256SUMS.txt SHA256 checksums for all files

Reproduction Steps

Prerequisites

# x86_64 Linux required
python3 -c "import platform; assert platform.machine() == 'x86_64', 'wrong arch'"
pip install tflite-support==0.4.4 Pillow numpy

Option A: Use pre-built artifacts (recommended)

# Models included in this repository
python3 reproduce_tflite_normalization_divergence.py

Option B: Build from scratch

pip install tensorflow-cpu==2.13.0 tflite-support==0.4.4 Pillow numpy
# The script auto-detects missing pre-built models and creates them
python3 reproduce_tflite_normalization_divergence.py

Docker (self-contained)

docker run --rm --platform linux/amd64 \
  -v "$(pwd)":/work \
  python:3.10-slim bash -c \
  'pip install tflite-support==0.4.4 Pillow numpy -q && python3 /work/reproduce_tflite_normalization_divergence.py'

Expected Output

=== TFLite NormalizationOptions Divergence Reproduction ===
Platform: Linux-...x86_64...
Python: 3.10.x

[Phase 1] Using pre-built model artifacts...
  clean SHA256:   e45db82dcc520253add7db59ab5c1dd4a3e18cd8c5e0e1b25b91ebd2f659ba99
  mutated SHA256: 54a8cd5160cef27d657c311dc6a4c795e23b6abf5e08d0b2bf451cd48673acb3

[Phase 3] Running Task Library ImageClassifier...
  Input: 224x224x3 gray (pixel value=128)
  Clean normalization:   (128 - 0.5) / 0.5 = 255.0
  Mutated normalization: (128 - 200.0) / 0.001 = -72000.0
  [CLEAN   mean=0.5 std=0.5] top3=[(2, 123.179596)]
  [MUTATED mean=200.0 std=0.001] top3=[(1, 96959.820312), (0, 17284.539062)]

  delta = 96836.64071655273

[Phase 4] Verdict...
DIVERGENCE_CONFIRMED β€” delta 96836.6407 >> threshold 0.001
Task Library applied NormalizationOptions from model metadata at inference time.
Adversarial mean/std values silently corrupt inference output for FLOAT32 inputs.

Evidence Summary

Metric Value
Clean top-1 score 123.179596
Mutated top-1 score 96959.820312
Delta 96836.64071655273
Threshold 0.001
Result DIVERGENCE_CONFIRMED
5x same-process runs ALL_PASS (stddev=0.0)
3x subprocess runs ALL_PASS
Determinism Fully deterministic

Distinctness from Prior TFLite Findings

This finding is distinct from two prior flite-support findings on all five dimensions:

Dimension This finding Prior finding A Prior finding B
FlatBuffer table NormalizationOptions SignatureDef AssociatedFile
Runtime stage Pre-inference (input preprocessing) Inference routing Post-inference (label lookup)
Effect Input tensor amplification Wrong subgraph executed Wrong label names
Code path NormalizationPreprocessingOp::Process() Subgraph routing Label resolution
Affected component float32 input tensor values Subgraph index Output label strings

Non-Claims

This finding does not claim:

  • Remote code execution (RCE)
  • Arbitrary code execution (ACE)
  • Memory corruption or buffer overflow
  • Universal inference bypass

The impact is silent inference output corruption via adversarial NormalizationOptions metadata.


References

  • TFLite metadata schema: metadata_schema.fbs
  • NormalizationOptions table
  • tflite-support version: 0.4.4 (PyPI manylinux2014_x86_64)
Downloads last month
1
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support