-
Notifications
You must be signed in to change notification settings - Fork 19.7k
Description
Description
The documentation for safe_mode in deserialize_keras_object only states it protects against "unsafe lambda deserialization."
However, the parameter name safe_mode implies broader safety guarantees. Users are not warned that safe_mode=True does NOT isolate built-in class name resolution from the custom object registry. This creates a documentation gap that could mislead developers into assuming stronger protections than exist.
Poc
import keras
from keras.src.saving import serialization_lib
class CustomDense(keras.layers.Layer):
def __init__(self, **kwargs):
super().__init__()
print("CustomDense called instead of real Dense")
def call(self, x):
return x
keras.utils.get_custom_objects()["Dense"] = CustomDense
config = {
"class_name": "Dense",
"config": {"units": 5, "name": "test"},
"registered_name": "Dense"
}
serialization_lib.deserialize_keras_object(config, safe_mode=True)
Observed Result
CustomDense called instead of real Dense
<CustomDense name=custom_dense, built=False>
Expected Behavior
safe_mode=True should resolve "Dense" to the built-in keras.layers.Dense, ignoring any custom registry overrides for built-in class names.
Actual Behavior
safe_mode=True silently resolves "Dense" to the custom registry entry, bypassing the built-in class entirely.
Suggested improvement
safe_mode parameter documentation to explicitly state that it only protects against Lambda layer deserialization and does not isolate built-in class names from overrides via keras.utils.get_custom_objects().