Instructions to use celvexgroup/modelscan-keras-loss-lambda-bypass-poc with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use celvexgroup/modelscan-keras-loss-lambda-bypass-poc with Keras:
# Available backend options are: "jax", "torch", "tensorflow". import os os.environ["KERAS_BACKEND"] = "jax" import keras model = keras.saving.load_model("hf://celvexgroup/modelscan-keras-loss-lambda-bypass-poc") - Notebooks
- Google Colab
- Kaggle
Upload 3 files
Browse files- README.md +41 -0
- control_lambda.keras +0 -0
- evil_loss.keras +0 -0
README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
tags:
|
| 4 |
+
- security
|
| 5 |
+
- coordinated-disclosure
|
| 6 |
+
- modelscan
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
# Benign PoC — modelscan Keras positional Lambda-scan bypass (compiled loss)
|
| 10 |
+
|
| 11 |
+
Coordinated-disclosure proof-of-concept for Protect AI `modelscan`, submitted via huntr (Model File Vulnerability).
|
| 12 |
+
|
| 13 |
+
modelscan's Keras/H5 Lambda detection (`KerasLambdaDetectScan` / `H5LambdaDetectScan`) is **positional**:
|
| 14 |
+
it flags only a top-level layer with `class_name=="Lambda"`. A marshalled-bytecode lambda serialized as
|
| 15 |
+
the model's compiled **loss** (in `compile_config`, which the DEFAULT `load_model(compile=True)`
|
| 16 |
+
deserializes) is never inspected — so a model that executes attacker bytecode on load+evaluate scans **clean**.
|
| 17 |
+
|
| 18 |
+
- `evil_loss.keras` — lambda in `compile_config.loss` → modelscan: **No issues found** (the bypass)
|
| 19 |
+
- `control_lambda.keras` — the **identical** benign function as a Lambda **layer** → modelscan: **MEDIUM `Lambda`** (control)
|
| 20 |
+
|
| 21 |
+
## Reproduce
|
| 22 |
+
|
| 23 |
+
```
|
| 24 |
+
pip install tensorflow modelscan
|
| 25 |
+
modelscan -p evil_loss.keras # -> No issues found (bypass)
|
| 26 |
+
modelscan -p control_lambda.keras # -> MEDIUM 'Lambda' from Keras (same function, caught as a layer)
|
| 27 |
+
|
| 28 |
+
python - <<'PY'
|
| 29 |
+
import keras, numpy as np
|
| 30 |
+
keras.config.enable_unsafe_deserialization()
|
| 31 |
+
m = keras.models.load_model("evil_loss.keras", safe_mode=False, compile=True)
|
| 32 |
+
m.evaluate(np.zeros((2,4)), np.zeros((2,1))) # -> writes /tmp/celvex_mfv_keras_marker.txt
|
| 33 |
+
PY
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
The lambda reconstructs from marshalled bytecode and runs when the loss is invoked (evaluate/fit) after a
|
| 37 |
+
default `load_model(compile=True, safe_mode=False)` — the same safe-mode premise as the accepted
|
| 38 |
+
Lambda-layer class, but from a config position modelscan does not scan.
|
| 39 |
+
|
| 40 |
+
**Strictly benign:** the lambda only writes a marker string (`CELVEX-MFV-KERAS-LOSS-MARKER`). No
|
| 41 |
+
weaponization. Validated against modelscan 0.8.8 + tensorflow/keras 3.15.0.
|
control_lambda.keras
ADDED
|
Binary file (10.8 kB). View file
|
|
|
evil_loss.keras
ADDED
|
Binary file (15.5 kB). View file
|
|
|