--- library_name: keras tags: - security - keras - modelscan - proof-of-concept license: apache-2.0 --- # Keras Native Non-Layer Lambda ModelScan Bypass PoC Benign security proof-of-concept for a ModelScan Keras Native scanner/runtime mismatch. ## Summary ModelScan 0.8.8 flags top-level Keras `Lambda` layers, but it misses marshalled Python `__lambda__` bytecode stored in other `.keras` native `config.json` fields. Keras 3.14.1 blocks these artifacts by default with `safe_mode=True`. If a workflow opts into unsafe deserialization with `safe_mode=False`, Keras consumes the artifact-carried lambda and executes benign marker code. This repository contains three variants of the same scanner weakness: 1. `Dense.activation` contains `class_name: "__lambda__"`. 2. `keras.ops.map` contains an inbound-node lambda argument. 3. `keras.ops.vectorized_map` contains a lambda in the operation config. ModelScan reports zero issues for all three `.keras` archives. ## Severity Medium, CVSS 5.3. Rationale: the impact is a scanner false negative for artifact-carried Python bytecode that can execute during unsafe Keras deserialization. The severity is capped because this is not a default Keras `safe_mode=True` bypass. ## Tested Versions - `keras==3.14.1` - `tensorflow==2.20.0` - `modelscan==0.8.8` - `h5py==3.16.0` - Python 3.12.3 ## Files - `variants/activation/activation_lambda_manual_config.keras` - `variants/ops_map/ops_map_inbound_lambda.keras` - `variants/vectorized_map/vectorized_map_lambda.keras` - `verify_all.py`: verifies safe-mode blocking, unsafe marker execution, lambda locations, and ModelScan output. - `results/`: captured local validation outputs. - `requirements.txt`: tested dependency versions. ## Reproduce ```bash python -m venv .venv . .venv/bin/activate pip install -r requirements.txt python verify_all.py ``` Expected result: - `safe_mode_true` starts with `blocked:` for all variants. - `marker_after_safe_mode_true` is `false` for all variants. - unsafe deserialization creates the expected benign marker for all variants. - `modelscan_total_issues` is `0` for all variants. - `all_passed` is `true`. ## Artifact Hashes ```text f43f6dd253cb5f4683a2903ea5b6d7ae744573c7f4fbdb82d584974709ee3be8 variants/activation/activation_lambda_manual_config.keras 2a900cb614d5e0b6eef831e0bd4caafc6503daf6d33963ec6a64f7fa447d6cdc variants/ops_map/ops_map_inbound_lambda.keras 536334212fdea8cf9a19cf71d0c4decd74442116eb31ee39aab0c9d28b13757e variants/vectorized_map/vectorized_map_lambda.keras ``` ## Impact A registry or deployment workflow can scan a `.keras` artifact with ModelScan, receive a clean result, and later execute artifact-carried Python bytecode if it loads the model with unsafe Keras deserialization enabled. The PoC keeps the effect benign by writing local marker files only. ## Limitations - Not a Keras default safe-mode bypass. - Requires `safe_mode=False` or equivalent unsafe deserialization opt-in. - Does not execute shell commands, access credentials, persist, or perform network activity. - Related public work exists for top-level/wrapped Lambda misses and HDF5 activation-field bypasses; this PoC demonstrates current Keras native `.keras` non-layer `__lambda__` fields. ## Suggested Mitigation ModelScan's Keras Native scanner should recursively inspect `config.json` for `class_name: "__lambda__"` and other unsafe deserialization markers, not only top-level layers whose `class_name` is `Lambda`.