CVE-2025-9906
Arbitrary Code execution in Keras Safe Mode
The Keras Model.load_model method can be exploited to achieve arbitrary code execution, even with safe_mode=True.
One can create a specially crafted .keras model archive that, when loaded via Model.load_model, will trigger arbitrary code to be executed. This is achieved by crafting a special config.json (a file within the .keras archive) that will invoke keras.config.enable_unsafe_deserialization() to disable safe mode. Once safe mode is disable, one can use the Lambda layer feature of keras, which allows arbitrary Python code in the form of pickled code. Both can appear in the same archive. Simply the keras.config.enable_unsafe_deserialization() needs to appear first in the archive and the Lambda with arbitrary code needs to be second.
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
Arbitrary Code execution in Keras Safe Mode
The Keras Model.load_model method can be exploited to achieve arbitrary code execution, even with safe_mode=True.
One can create a specially crafted .keras model archive that, when loaded via Model.load_model, will trigger arbitrary code to be executed. This is achieved by crafting a special config.json (a file within the .keras archive) that will invoke keras.config.enable_unsafe_deserialization() to disable safe mode. Once safe mode is disable, one can use the Lambda layer feature of keras, which allows arbitrary Python code in the form of pickled code. Both can appear in the same archive. Simply the keras.config.enable_unsafe_deserialization() needs to appear first in the archive and the Lambda with arbitrary code needs to be second.
- Record
CVE-2025-9906- 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-30281
8.6
The Keras Model.load_model method can be exploited to achieve arbitrary code execution, even with safe_mode=True.
One can create a specially crafted .keras model archive that, when loaded via Model.load_model, will trigger arbitrary code to be executed. This is achieved by crafting a special config.json (a file within the .keras archive) that will invoke keras.config.enable_unsafe_deserialization() to disable safe mode. Once safe mode is disable, one can use the Lambda layer feature of keras, which allows arbitrary Python code in the form of pickled code. Both can appear in the same archive. Simply the keras.config.enable_unsafe_deserialization() needs to appear first in the archive and the Lambda with arbitrary code needs to be second.
- Record
EUVD-2025-30281- 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-36fq-jgmw-4r9c
8.7
Keras is vulnerable to Deserialization of Untrusted Data
Arbitrary Code Execution in Keras
Keras versions prior to 3.11.0 allow for arbitrary code execution when loading a crafted .keras model archive, even when safe_mode=True.
The issue arises because the archive’s config.json is parsed before layer deserialization. This can invoke keras.config.enable_unsafe_deserialization(), effectively disabling safe mode from within the loading process itself. An attacker can place this call first in the archive and then include a Lambda layer whose function is deserialized from a pickle, leading to the execution of attacker-controlled Python code as soon as a victim loads the model file.
Exploitation requires a user to open an untrusted model; no additional privileges are needed. The fix in version 3.11.0 enforces safe-mode semantics before reading any user-controlled configuration and prevents the toggling of unsafe deserialization via the config file.
Affected versions: < 3.11.0 Patched version: 3.11.0
It is recommended to upgrade to version 3.11.0 or later and to avoid opening untrusted model files.
- Record
GHSA-36fq-jgmw-4r9c- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
NVD
8.6
The Keras Model.load_model method can be exploited to achieve arbitrary code execution, even with safe_mode=True.
One can create a specially crafted .keras model archive that, when loaded via Model.load_model, will trigger arbitrary code to be executed. This is achieved by crafting a special config.json (a file within the .keras archive) that will invoke keras.config.enable_unsafe_deserialization() to disable safe mode. Once safe mode is disable, one can use the Lambda layer feature of keras, which allows arbitrary Python code in the form of pickled code. Both can appear in the same archive. Simply the keras.config.enable_unsafe_deserialization() needs to appear first in the archive and the Lambda with arbitrary code needs to be second.
- Record
CVE-2025-9906- 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.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
OSV
8.6
Arbitrary Code execution in Keras Safe Mode
The Keras Model.load_model method can be exploited to achieve arbitrary code execution, even with safe_mode=True.
One can create a specially crafted .keras model archive that, when loaded via Model.load_model, will trigger arbitrary code to be executed. This is achieved by crafting a special config.json (a file within the .keras archive) that will invoke keras.config.enable_unsafe_deserialization() to disable safe mode. Once safe mode is disable, one can use the Lambda layer feature of keras, which allows arbitrary Python code in the form of pickled code. Both can appear in the same archive. Simply the keras.config.enable_unsafe_deserialization() needs to appear first in the archive and the Lambda with arbitrary code needs to be second.
- Record
CVE-2025-9906- 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
OSVDEBIAN-CVE-2025-9906
7.3
The Keras Model.load_model method can be exploited to achieve arbitrary code execution, even with safe_mode=True. One can create a specially crafted .keras model archive that, when loaded via Model.load_model, will trigger arbitrary code to be executed. This is achieved by crafting a special config.json (a file within the .keras archive) that will invoke keras.config.enable_unsafe_deserialization() to disable safe mode. Once safe mode is disable, one can use the Lambda layer feature of keras, which allows arbitrary Python code in the form of pickled code. Both can appear in the same archive. Simply the keras.config.enable_unsafe_deserialization() needs to appear first in the archive and the Lambda with arbitrary code needs to be second.
- Record
DEBIAN-CVE-2025-9906- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
Show 4 moreShow less
OSVGHSA-36fq-jgmw-4r9c
8.7
Keras is vulnerable to Deserialization of Untrusted Data
Arbitrary Code Execution in Keras
Keras versions prior to 3.11.0 allow for arbitrary code execution when loading a crafted .keras model archive, even when safe_mode=True.
The issue arises because the archive’s config.json is parsed before layer deserialization. This can invoke keras.config.enable_unsafe_deserialization(), effectively disabling safe mode from within the loading process itself. An attacker can place this call first in the archive and then include a Lambda layer whose function is deserialized from a pickle, leading to the execution of attacker-controlled Python code as soon as a victim loads the model file.
Exploitation requires a user to open an untrusted model; no additional privileges are needed. The fix in version 3.11.0 enforces safe-mode semantics before reading any user-controlled configuration and prevents the toggling of unsafe deserialization via the config file.
Affected versions: < 3.11.0 Patched version: 3.11.0
It is recommended to upgrade to version 3.11.0 or later and to avoid opening untrusted model files.
- Record
GHSA-36fq-jgmw-4r9c- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
OSVPYSEC-2025-76
7.3
The Keras Model.load_model method can be exploited to achieve arbitrary code execution, even with safe_mode=True.
One can create a specially crafted .keras model archive that, when loaded via Model.load_model, will trigger arbitrary code to be executed. This is achieved by crafting a special config.json (a file within the .keras archive) that will invoke keras.config.enable_unsafe_deserialization() to disable safe mode. Once safe mode is disable, one can use the Lambda layer feature of keras, which allows arbitrary Python code in the form of pickled code. Both can appear in the same archive. Simply the keras.config.enable_unsafe_deserialization() needs to appear first in the archive and the Lambda with arbitrary code needs to be second.
- Record
PYSEC-2025-76- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
OSVUBUNTU-CVE-2025-9906
8.6
The Keras Model.load_model method can be exploited to achieve arbitrary code execution, even with safe_mode=True. One can create a specially crafted .keras model archive that, when loaded via Model.load_model, will trigger arbitrary code to be executed. This is achieved by crafting a special config.json (a file within the .keras archive) that will invoke keras.config.enable_unsafe_deserialization() to disable safe mode. Once safe mode is disable, one can use the Lambda layer feature of keras, which allows arbitrary Python code in the form of pickled code. Both can appear in the same archive. Simply the keras.config.enable_unsafe_deserialization() needs to appear first in the archive and the Lambda with arbitrary code needs to be second.
- Record
UBUNTU-CVE-2025-9906- 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.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
OSVAZL-67508 No score
CVE-2025-9906 affecting package keras for versions less than 3.3.3-4
The Keras Model.load_model method can be exploited to achieve arbitrary code execution, even with safe_mode=True.
One can create a specially crafted .keras model archive that, when loaded via Model.load_model, will trigger arbitrary code to be executed. This is achieved by crafting a special config.json (a file within the .keras archive) that will invoke keras.config.enable_unsafe_deserialization() to disable safe mode. Once safe mode is disable, one can use the Lambda layer feature of keras, which allows arbitrary Python code in the form of pickled code. Both can appear in the same archive. Simply the keras.config.enable_unsafe_deserialization() needs to appear first in the archive and the Lambda with arbitrary code needs to be second.
- Record
AZL-67508- Updated
- 2026-11-05
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
kerasPyPI |
before 3.11.0 | 3.11.0 |
kerasAzure Linux:3 |
before 3.3.3-4 | 3.3.3-4 |
kerasDebian:11 |
All versions, plus listed versions 2.3.1+dfsg-32.3.1+dfsg2-1 |
None known |
kerasPyPI |
before 3.11.0, plus listed versions 0.2.00.3.00.3.10.3.20.3.3 Show 45 moreShow less1.0.01.0.11.0.21.0.31.0.41.0.51.0.61.0.71.0.81.1.01.1.11.1.21.2.01.2.11.2.22.0.02.0.12.0.22.0.32.0.42.0.52.0.62.0.72.0.82.0.92.1.02.1.12.1.22.1.32.1.42.1.52.1.62.10.02.10.0rc02.10.0rc12.11.02.11.0rc02.11.0rc12.11.0rc22.11.0rc32.12.02.12.0rc02.12.0rc12.13.12.13.1rc0 |
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-9906 is a high vulnerability (CVSS 8.6) in Google Keras, published September 19, 2025. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.20%, the 10th percentile. Fixed in keras 3.11.0.
References
github.com/keras-team/keras/pull/21429
nvd.nist.gov/vuln/detail/CVE-2025-9906
github.com/keras-team/keras/commit/713172ab56b864e59e2aa79b1a51b0e728bba858
github.com/keras-team/keras/releases/tag/v3.11.0
osv.dev/vulnerability/CVE-2025-9906
github.com/pypa/advisory-database/tree/main/vulns/keras/PYSEC-2025-76.yaml
Left out here: 58 versions. The JSON record has them.