Downloads · 30 days
3
4% of all-time downloads
Hironabe333/keras-duplicate-weights-h5-poc
keras-duplicate-weights-h5-poc is a machine learning model from Hironabe333. Use it for the machine learning task on the model card, and read the license before you ship it in a product. It is set up for keras.
A .keras file is a ZIP archive. When it contains two entries both named model.weights.h5, Python's zipfile.ZipFile.read() resolves to the last entry. keras.saving.loadmodel() therefore loads trained weights from the l…
Downloads · 30 days
3
4% of all-time downloads
All-time downloads
83
Public
Repo size
—
Likes
0
Public
Click a slice to open those files.
.keras13.4 KB · 47%
From the Hugging Face model README
A .keras file is a ZIP archive. When it contains two entries both named
model.weights.h5, Python's zipfile.ZipFile.read() resolves to the last
entry. keras.saving.load_model() therefore loads trained weights from the later
entry. safe_mode=True does not prevent this. ModelScan 0.8.8 reports 0 issues.
This issue affects the weight archive member, model.weights.h5, rather than
model architecture metadata. The crafted archive contains a single unchanged
config.json; only the weight file member is duplicated. The model architecture
remains the same, but the trained parameters selected by the loader change.
| Architecture/config duplicate | This report | |
|---|---|---|
| Duplicate member | config.json | model.weights.h5 |
| Attack target | model architecture / config | trained weights (parameters) |
| Manipulation | architecture/config behavior | direct parameter replacement |
config.json in this PoC | (not applicable) | single and unchanged |
| Required mitigation | reject duplicate config metadata | reject duplicate weight archive members |
KERAS_BACKEND=torch (no TensorFlow required)pip install -r requirements.txt
KERAS_BACKEND=torch python make_duplicate_weights_h5.py
KERAS_BACKEND=torch python check_duplicate_weights_h5.py
The scripts confirm that Keras loads the second model.weights.h5 entry
and produces different outputs from the baseline model.
| File | Description |
|---|---|
benign_weights_single.keras | Baseline model (single model.weights.h5, benign weights) |
dup_model_weights_h5.keras | Crafted file: first entry benign, second entry malicious weights |
make_duplicate_weights_h5.py | Generates both files |
check_duplicate_weights_h5.py | Verifies loader behavior and inference differential |
A reviewer or tool that inspects only one model.weights.h5 archive member
would see benign trained weights:
kernel = [[1.0], [1.0]] bias = [0.0] → output = x0 + x1
Loading the file with keras.saving.load_model() — including safe_mode=True
— produces different output, because Keras resolves to the last duplicate entry:
kernel = [[-1.0], [-1.0]] bias = [5.0] → output = -(x0+x1) + 5
Observed inference differential:
| Input | Benign output | Crafted model output |
|---|---|---|
| [1.0, 0.0] | 1.0 | 4.0 |
| [0.0, 1.0] | 1.0 | 4.0 |
| [1.0, 1.0] | 2.0 | 3.0 |