CVE-2026-12570 Overview
CVE-2026-12570 is a denial of service (DoS) vulnerability in keras-team/keras versions <= 3.15.0. The flaw resides in the H5IOStore.__getitem__ method in keras/src/saving/saving_lib.py, which fails to validate dataset shape or size when loading .keras model files. A specially crafted .keras file passed to keras.models.load_model() triggers unbounded memory allocation, forcing an out-of-memory (OOM) condition that terminates the process with exit code 137. The vulnerability bypasses the earlier fix for CVE-2026-0897, which addressed a similar issue only in KerasFileEditor. Machine learning pipelines that ingest untrusted models from public registries are directly exposed [CWE-770].
Critical Impact
Loading a malicious .keras model file causes uncontrolled memory allocation, terminating the Python process and disrupting ML inference or training pipelines.
Affected Products
- keras-team/keras versions <= 3.15.0
- Applications invoking keras.models.load_model() on untrusted .keras files
- ML pipelines consuming models from public repositories or third-party registries
Discovery Timeline
- 2026-08-10 - CVE-2026-12570 published to NVD
- 2026-08-10 - Last updated in NVD database
Technical Details for CVE-2026-12570
Vulnerability Analysis
The .keras file format wraps model weights inside an HDF5 container. When Keras deserializes a model, H5IOStore.__getitem__ retrieves datasets from the archive without validating the declared shape against the actual bytes stored on disk. HDF5 supports chunked and compressed datasets, allowing a file to declare a very large in-memory shape while occupying almost no physical storage. Reading such a dataset forces the runtime to allocate memory proportional to the declared shape, exhausting host memory and terminating the Python interpreter. This class of flaw is commonly referred to as an HDF5 "shape bomb" and maps to uncontrolled resource consumption [CWE-770].
Root Cause
The root cause is missing size validation in the model loading path. The prior remediation for CVE-2026-0897 added guards only to KerasFileEditor, leaving load_model() and load_weights() reachable through H5IOStore unprotected. Any dataset with a declared in-memory size disproportionate to its on-disk footprint proceeds directly to allocation.
Attack Vector
An attacker publishes a malicious .keras file to a model registry, Git repository, or shared storage. When a victim pipeline calls keras.models.load_model() on the file, the process attempts to materialize the oversized dataset and is killed by the operating system with SIGKILL (exit code 137). Exploitation requires user interaction to load the file but no authentication.
return group
+# Guard against HDF5 "shape bomb" datasets: a dataset can declare an enormous
+# shape while storing almost nothing on disk (e.g. chunked + gzip-compressed
+# with only a fill value), which forces a huge allocation when it is read into
+# memory (CWE-789 / CWE-409). For datasets whose declared in-memory size is
+# above this floor, we require it to stay within `_H5_DATASET_MAX_EXPANSION` of
+# the bytes actually stored on disk. Genuine arrays (even compressed) satisfy
+# this; shape/decompression bombs, which store next to nothing, do not.
+_H5_DATASET_BOMB_FLOOR_BYTES = 1 << 32 # 4 GiB
+_H5_DATASET_MAX_EXPANSION = 1000
+
+
def safe_get_h5_dataset(group, name):
"""Retrieve a Dataset within a given Group.
Source: GitHub Keras Commit 4933ea4. The patch introduces a 4 GiB floor and a 1000x maximum expansion ratio between declared in-memory size and on-disk bytes, rejecting shape-bomb datasets before allocation.
Detection Methods for CVE-2026-12570
Indicators of Compromise
- Python processes handling .keras files terminating with exit code 137 (SIGKILL from the OOM killer).
- Kernel oom-killer log entries referencing Python interpreters running Keras workloads.
- Sudden RSS growth to host memory limits during calls to keras.models.load_model().
- .keras archives containing HDF5 datasets whose declared shape vastly exceeds their compressed on-disk size.
Detection Strategies
- Inspect incoming .keras files with h5py to compare each dataset's dtype.itemsize * numpy.prod(shape) against its id.get_storage_size() before loading.
- Reject archives that exceed a reasonable expansion ratio, mirroring the upstream _H5_DATASET_MAX_EXPANSION threshold of 1000.
- Correlate ML worker OOM terminations with the specific model artifact loaded in the preceding request.
Monitoring Recommendations
- Emit metrics for memory usage of model-loading workers and alert on rapid allocation spikes.
- Log the source, hash, and provenance of every .keras file loaded by production pipelines.
- Aggregate exit-code-137 terminations across ML fleets in a central log platform to spot recurring malicious artifacts.
How to Mitigate CVE-2026-12570
Immediate Actions Required
- Upgrade keras to a version containing commit 4933ea4a5b3fcc24ceacdc276f5bb5dfbd06756c or later.
- Treat all .keras files from external sources as untrusted until they pass shape-bomb validation.
- Isolate model-loading workers in memory-capped containers so an OOM event cannot affect neighboring services.
Patch Information
The fix is applied in keras/src/saving/saving_lib.py via the referenced GitHub Keras Commit. It introduces _H5_DATASET_BOMB_FLOOR_BYTES (4 GiB) and _H5_DATASET_MAX_EXPANSION (1000) constants, and the safe_get_h5_dataset helper rejects datasets whose declared size exceeds the floor and expands beyond the allowed ratio relative to on-disk bytes. Additional context is available on the Huntr Security Bounty report.
Workarounds
- Pre-scan .keras files with a validator that opens the HDF5 container read-only and enforces a maximum expansion ratio before invoking load_model().
- Run model loading inside a container with strict --memory limits and a restart policy to contain OOM events.
- Restrict production pipelines to signed model artifacts published from trusted internal registries.
# Configuration example: cap memory for untrusted model loading
docker run --rm \
--memory=2g \
--memory-swap=2g \
--pids-limit=128 \
--read-only \
-v "$PWD/models:/models:ro" \
keras-loader:patched \
python -c "import keras; keras.models.load_model('/models/untrusted.keras')"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

