Keras duplicate model.weights.h5 backdoor PoC

This repository contains a proof-of-concept for a Keras .keras archive ambiguity where duplicate model.weights.h5 entries are accepted. Keras resolves the required weights member to the later duplicate entry, enabling hidden trigger-based backdoor weights while config.json, metadata.json, and the first weights entry can remain benign.

This is not a Lambda layer deserialization issue. The CNN PoC uses standard Keras layers: Conv2D, Flatten, and Dense.

Main PoC

  • Model format: .keras
  • Architecture: Conv2D -> Flatten -> Dense
  • Trigger: bottom-right 2x2 image patch
  • Poisoned archive: duplicate model.weights.h5
  • First weights entry: benign / matches clean model
  • Later duplicate weights entry: contains trigger backdoor
  • Keras load result: loads without warning
  • safe_mode=True: does not reject
  • ModelScan: No issues found
  • Load/save laundering: duplicate-entry evidence disappears, but the backdoor remains active

Key files

  • cnn_image_backdoor_clean_baseline.keras
  • cnn_image_backdoor_duplicate_weights_trigger.keras
  • cnn_image_backdoor_pipeline_normalized.keras
  • evidence_bundle_keras_duplicate_weights_backdoor.zip

Suggested remediation

Keras should reject duplicate required archive members before reading or extracting model contents:

  • metadata.json
  • config.json
  • model.weights.h5
  • model.weights.npz
Downloads last month
19
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support