Skip to content

[Docs] safe_mode=True does not isolate built-in class names from get_custom_objects() registry #22466

@amadhan882

Description

@amadhan882

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().

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:docsNeed to modify the documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions