
Allocation of Resources Without Limits or Throttling in the HDF5 weight loading component in Google Keras 3.0.0 through 3.13.0 on all platforms allows a remote attacker to cause a Denial of Service (DoS) through memory exhaustion and a crash of the Python interpreter via a crafted .keras
| Field | Details |
|---|---|
| CVE ID | CVE-2026-0897 |
| Package | keras (Google Keras) |
| Registry | PyPI |
| Affected Versions | 3.0.0 through 3.13.0 (inclusive) |
| Vulnerability Type | CWE-770: Allocation of Resources Without Limits or Throttling |
| CVSS Score | 7.1 High (CVSS 4.0, CNA: Google Inc.) |
| CVSS Vector | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N |
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | None |
| User Interaction | Passive (victim loads a model file) |
| Availability Impact | High |
| Confidentiality Impact | None |
| Integrity Impact | None |
| NVD Published | January 15, 2026 |
| NVD Last Modified | January 23, 2026 |
| Source / CNA | Google Inc. |
| Reported By | HyperPS (Sarvesh Patil) via huntr.dev / GHSA |
| Fix Status | Merged — PR #21880 |
A Denial of Service vulnerability exists in the HDF5 weight loading component of Google Keras versions 3.0.0 through 3.13.0 on all platforms. The vulnerability is caused by the absence of any validation or throttling when processing HDF5 dataset shape metadata declared inside a .keras archive.
The HDF5 format permits datasets to declare their shape (tensor dimensions) as metadata. When Keras loads model weights from a .keras archive, it reads this declared shape and attempts to allocate a corresponding block of memory before any data is transferred. Because Keras performs no bounds check on the declared shape prior to allocation, an attacker can craft a model.weights.h5 file that declares an astronomically large shape — for example (1000000, 1000000, 1000000) — causing Keras to attempt a petabyte-scale memory allocation. This exhausts all available system memory and crashes the Python interpreter.
No inference or further interaction is required after the model is loaded. The attack is fully triggered at load time.
| File | Description |
|---|---|
keras/src/saving/file_editor.py | KerasFileEditor._extract_weights_from_store() — reads HDF5 dataset shape and allocates memory without size validation or throttling |
The vulnerability is located specifically in the KerasFileEditor class, which is responsible for deserializing model weight tensors from HDF5 stores embedded inside .keras archives.
| Metric | Value | Meaning |
|---|---|---|
| Attack Vector (AV) | Network | Exploitable remotely via a distributed model file |
| Attack Complexity (AC) | Low | No special conditions or race conditions required |
| Attack Requirements (AT) | None | No prerequisite deployment configuration needed |
| Privileges Required (PR) | None | No authentication or account required |
| User Interaction (UI) | Passive | Victim must load the malicious .keras archive |
| Vulnerable System Availability (VA) | High | Python interpreter crashes; service becomes completely unavailable |
| Vulnerable System Confidentiality (VC) | None | No data disclosure |
| Vulnerable System Integrity (VI) | None | No data modification |
| Subsequent System Impact (SC/SI/SA) | None | Impact is contained to the loading process |
.keras model archives from untrusted or user-supplied sources is vulnerable| Context | Risk |
|---|---|
Public model serving APIs that accept user-uploaded .keras files | Attacker crashes the inference service with a single request |
| ML platforms hosting community model downloads (e.g., Hugging Face) | Poisoned model causes DoS for any researcher who downloads and loads it |
| Federated learning environments | Malicious participant distributes a crafted weight file to crash coordinator or peer nodes |
| CI/CD pipelines that load model checkpoints | A compromised or substituted checkpoint causes pipeline failure and unavailability |
| Chatbots or NLP services that hot-reload models at runtime | Single malicious reload request brings the service down |
The HDF5 file format stores tensor metadata — including shape declarations — separately from the actual data bytes. When KerasFileEditor._extract_weights_from_store() encounters a dataset entry, it reads the declared shape and calls NumPy to pre-allocate an array of the corresponding dimensions before reading any data from disk.
Because the shape is metadata, a minimal HDF5 file can declare a shape that would require petabytes of memory while the file itself remains only a few kilobytes in size. The ratio of file size to allocation size makes this a highly effective amplification attack.
A shape such as (1000000, 1000000, 1000000) with a 32-bit float dtype would request approximately 4,000 petabytes of memory. The OS out-of-memory killer or the Python allocator will crash the process nearly instantly.
# keras/src/saving/file_editor.py (pre-fix, simplified)
def _extract_weights_from_store(self, h5_file, inner_path=""):
for key in h5_file.keys():
obj = h5_file[key]
if isinstance(obj, h5py.Dataset):
# Shape is read from metadata — no validation performed
shape = obj.shape
# NumPy attempts to allocate based on declared shape
data = np.zeros(shape, dtype=obj.dtype) # VULNERABLE: unbounded allocation
The absence of any check on shape before calling np.zeros() is the root cause.
This information is provided for educational and defensive purposes only. Do not test against systems you do not own or have explicit authorization to test.
.keras Archive# generate_shape_bomb.py
import h5py
import zipfile
import json
import os
# Step 1: Create a minimal HDF5 weights file with a hostile shape declaration
with h5py.File("model.weights.h5", "w") as f:
grp = f.create_group("layers/dense/vars")
# Declare shape that would require petabytes of memory to allocate
# Actual data is never written — only the metadata shape declaration is malicious
grp.create_dataset(
"0",
shape=(0,), # actual stored data: empty
maxshape=(None,),
dtype="float32",
data=[]
)
# Override shape metadata to declare hostile dimensions
# (achieved via direct HDF5 attribute manipulation in a real attack)
# Step 2: Package into a valid .keras archive structure
config = {
"class_name": "Sequential",
"config": {"name": "sequential", "trainable": True, "layers": []},
"keras_version": "3.0.0",
"backend": "tensorflow"
}