Miggo Logo

CVE-2025-8747: Keras safe mode bypass vulnerability

N/A

CVSS Score

Basic Information

EPSS Score
0.04125%
Published
8/11/2025
Updated
8/11/2025
KEV Status
No
Technology
TechnologyPython

Technical Details

CVSS Vector
-
Package NameEcosystemVulnerable VersionsFirst Patched Version
keraspip>= 3.0.0, < 3.11.03.11.0

Vulnerability Intelligence
Miggo AIMiggo AI

Miggo AIRoot Cause Analysis

The vulnerability is a classic case of unsafe deserialization of untrusted data. The root cause is in the _retrieve_class_or_fn function within keras/src/saving/serialization_lib.py, which was responsible for dynamically loading classes needed to reconstruct a Keras model from a .keras file. The original implementation did not validate the classes being loaded, allowing an attacker to craft a model file that, when loaded, would cause Keras to instantiate arbitrary classes, leading to remote code execution.

The patch addresses this by introducing a KerasSaveable mixin class. The _retrieve_class_or_fn function was modified to check if the class being loaded is a subclass of KerasSaveable. This ensures that only classes explicitly marked as safe for deserialization by the Keras developers can be loaded, effectively blocking the loading of arbitrary, and potentially malicious, classes.

The primary entry point for an attack is the keras.models.load_model API, which is what a user would call to load a model. This function would appear at the top of a stack trace during exploitation, followed by deserialize_keras_object and finally the core vulnerable function, _retrieve_class_or_fn.

Vulnerable functions

Only Mi**o us*rs **n s** t*is s**tion

WAF Protection Rules

WAF Rule

* s*** mo** *yp*ss vuln*r**ility in t** `Mo**l.lo**_mo**l` m*t*o* in K*r*s v*rsions *.*.* t*rou** *.**.* *llows *n *tt**k*r to ***i*v* *r*itr*ry *o** *x**ution *y *onvin*in* * us*r to lo** * sp**i*lly *r**t** `.k*r*s` mo**l *r**iv*.

Reasoning

T** vuln*r**ility is * *l*ssi* **s* o* uns*** **s*ri*liz*tion o* untrust** **t*. T** root **us* is in t** `_r*tri*v*_*l*ss_or_*n` *un*tion wit*in `k*r*s/sr*/s*vin*/s*ri*liz*tion_li*.py`, w*i** w*s r*sponsi*l* *or *yn*mi**lly lo**in* *l*ss*s n***** to