Downloads · 30 days
13
9% of all-time downloads
optimus-fulcria/modelscan-keras-bypass-poc
modelscan-keras-bypass-poc is a machine learning model from optimus-fulcria. 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.
ModelScan v0.8.8's Keras scanner (KerasLambdaDetectScan) only checks for Lambda layers at the top level of modelconfig["config"]["layers"]. Lambda layers nested inside sub-models (Functional, Sequential) or wrapper la…
Downloads · 30 days
13
9% of all-time downloads
All-time downloads
144
Public
Repo size
—
Likes
0
Public
Click a slice to open those files.
.md2 KB · 37%
From the Hugging Face model README
ModelScan v0.8.8's Keras scanner (KerasLambdaDetectScan) only checks for Lambda layers at the top level of model_config["config"]["layers"]. Lambda layers nested inside sub-models (Functional, Sequential) or wrapper layers (TimeDistributed, Bidirectional) are not detected.
nested_lambda_bypass.keras)Lambda layer hidden inside a nested Functional sub-model. ModelScan sees the outer layer as class_name: "Functional" and skips it.
wrapper_lambda_bypass.keras)Lambda layer wrapped in a TimeDistributed wrapper. ModelScan sees class_name: "TimeDistributed" and skips it.
In modelscan/scanners/keras/scan.py lines 119-131:
lambda_layers = [
layer.get("config", {}).get("function", {})
for layer in model_config_data.get("config", {}).get("layers", {})
if layer.get("class_name", {}) == "Lambda"
]
This only iterates the top-level layers list. It does NOT recursively check:
config.layers[n].config.layers)layer field in TimeDistributed/Bidirectional)When a user loads a .keras file that passes ModelScan with 0 issues:
import keras
model = keras.models.load_model("nested_lambda_bypass.keras", safe_mode=False)
# Arbitrary code executes via marshal.loads in Lambda.from_config()
The Lambda function is deserialized via:
Functional.from_config() → process_layer() → recursive deserialize_keras_object()Lambda.from_config() → python_utils.func_load()func_load() → codecs.decode(base64) → marshal.loads() → types.FunctionType() → ACEpip install modelscan[keras]
modelscan -p nested_lambda_bypass.keras
# Output: No issues found (0 Lambda layers detected)
# But the file contains a malicious Lambda layer with marshal.loads code execution