CVE-2025-9905 Overview
CVE-2025-9905 is an arbitrary code execution vulnerability in the Keras deep learning library. The flaw resides in the Model.load_model method when processing legacy .h5/.hdf5 model archives. Attackers can craft a malicious HDF5 model file that abuses the Keras Lambda layer feature, which permits arbitrary Python code embedded as pickled data. The vulnerability stems from Model.load_model failing to honor the safe_mode=True option when reading .h5 archives, bypassing the primary safeguard against malicious deserialization. Any developer or automated pipeline loading an untrusted .h5 model will execute attacker-controlled Python code in the host process. This affects Keras 3 environments that continue to support the legacy HDF5 format for backwards compatibility.
Critical Impact
Loading an untrusted .h5/.hdf5 Keras model triggers arbitrary Python code execution even when safe_mode=True is explicitly set.
Affected Products
- Keras (keras-team/keras) Python package
- Keras 3 releases supporting the legacy .h5/.hdf5 format
- Machine learning pipelines that call Model.load_model on HDF5 archives
Discovery Timeline
- 2025-09-19 - CVE-2025-9905 published to the National Vulnerability Database
- 2026-06-17 - Last updated in NVD database
Technical Details for CVE-2025-9905
Vulnerability Analysis
The vulnerability is classified as an Improper Control of Dynamically-Managed Code Resources issue ([CWE-913]). Keras supports Lambda layers, which serialize arbitrary Python callables using Python's pickle module. When Keras loads a model, safe_mode=True should block deserialization of such layers because unpickling untrusted data enables arbitrary code execution.
For modern .keras archives, the safe-mode check is enforced. For legacy .h5/.hdf5 archives, the code path that reconstructs Lambda layers does not consult the safe_mode flag. As a result, Model.load_model(path, safe_mode=True) still invokes pickle.loads on attacker-supplied bytes when the file is HDF5. This turns model loading into a code execution primitive whenever the model source is not fully trusted.
Root Cause
The root cause is a missing security check in the legacy HDF5 loading path. The safe_mode parameter is propagated for the JSON-based .keras format but is not evaluated before deserializing Lambda layer configurations stored inside .h5 archives. Pickled Python objects embedded in the layer configuration are unmarshalled directly, executing any __reduce__ handlers defined by the attacker.
Attack Vector
Exploitation requires a victim to load an attacker-supplied .h5 or .hdf5 file with Model.load_model. Typical delivery paths include model marketplaces, shared research repositories, MLOps pipelines that fetch models from remote storage, and supply-chain compromise of internal model registries. Once loaded, the payload executes with the privileges of the Python process, providing access to training data, cloud credentials, and downstream infrastructure. See the GitHub Security Advisory GHSA-36rr-ww3j-vrjv for the maintainer analysis.
No verified public proof-of-concept code is available. The vulnerability mechanism is documented in the upstream advisory and in Keras Pull Request #21602, which introduces the fix.
Detection Methods for CVE-2025-9905
Indicators of Compromise
- Presence of .h5 or .hdf5 model files originating from untrusted sources or unexpected authors.
- HDF5 archives that contain Lambda layer configurations with embedded pickle byte streams.
- Python processes spawning shells, network utilities, or credential access tools shortly after calling keras.models.load_model.
- Outbound connections from ML training or inference hosts to unfamiliar domains during model load operations.
Detection Strategies
- Inspect .h5 archives with HDF5 tooling and flag files containing Lambda layer entries with serialized Python objects.
- Monitor Python interpreters running Keras for unexpected child processes such as sh, bash, cmd.exe, or powershell.exe.
- Alert on pickle.loads or marshal.loads calls originating from Keras model loading code paths in application telemetry.
Monitoring Recommendations
- Log all model ingestion events in ML pipelines, including file hash, source URL, and loading user.
- Correlate model loading activity with process creation and network connection telemetry from EDR agents.
- Track outbound traffic from data science workstations and Jupyter notebook servers for anomalous destinations following model loads.
How to Mitigate CVE-2025-9905
Immediate Actions Required
- Upgrade Keras to the patched release referenced in Keras Pull Request #21602 as soon as it is available in your dependency manager.
- Inventory all .h5 and .hdf5 models in use and validate their provenance before further loading.
- Restrict Model.load_model usage to models produced or signed by trusted internal sources.
- Isolate model loading workloads in sandboxed containers or short-lived compute environments without production credentials.
Patch Information
The Keras maintainers released the fix through Keras Pull Request #21602. Details of impact and remediation are published in GitHub Security Advisory GHSA-36rr-ww3j-vrjv. Upgrade to the fixed Keras version and rebuild any container images that pin an earlier release.
Workarounds
- Convert trusted legacy models from .h5/.hdf5 to the modern .keras format and load only that format going forward.
- Refuse to load .h5 or .hdf5 files programmatically until the patched Keras version is deployed.
- Run model deserialization inside sandboxed processes with no network egress and no access to secrets or cloud IAM roles.
- Add pre-load scanning that rejects HDF5 archives containing Lambda layer configurations with serialized Python objects.
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

