CVE-2025-9906

7.3 HIGH

📋 TL;DR

CVE-2025-9906 is a critical vulnerability in Keras that allows arbitrary code execution when loading specially crafted .keras model files. Attackers can bypass safe_mode=True protection by embedding malicious configuration that disables safe deserialization, then execute arbitrary Python code via Lambda layers. This affects any system using Keras to load untrusted model files.

💻 Affected Systems

Products:
  • Keras
Versions: All versions prior to the fix in PR #21429
Operating Systems: All platforms running Python with Keras
Default Config Vulnerable: ⚠️ Yes
Notes: Vulnerable even with safe_mode=True enabled, which is the default setting for load_model().

📦 What is this software?

⚠️ Risk & Real-World Impact

🔴

Worst Case

Complete system compromise with attacker gaining full control over the affected system, potentially leading to data theft, ransomware deployment, or lateral movement within networks.

🟠

Likely Case

Remote code execution on systems loading malicious Keras models from untrusted sources, enabling data exfiltration, backdoor installation, or cryptocurrency mining.

🟢

If Mitigated

Limited impact if models are only loaded from trusted sources with proper validation and sandboxing in place.

🌐 Internet-Facing: HIGH if applications accept and load .keras files from external users via web interfaces or APIs.
🏢 Internal Only: MEDIUM if models are shared internally but could be compromised via supply chain attacks or insider threats.

🎯 Exploit Status

Public PoC: ⚠️ Yes
Weaponized: LIKELY
Unauthenticated Exploit: ⚠️ Yes
Complexity: LOW

Exploit requires creating a malicious .keras archive with specific file ordering but is straightforward for attackers with Python knowledge.

🛠️ Fix & Mitigation

✅ Official Fix

Patch Version: Version containing PR #21429 fix

Vendor Advisory: https://github.com/keras-team/keras/pull/21429

Restart Required: No

Instructions:

1. Update Keras to version containing PR #21429 fix. 2. Run: pip install --upgrade keras. 3. Verify safe_mode=True cannot be disabled via config.json in .keras archives.

🔧 Temporary Workarounds

Disable Lambda layer loading

all

Prevent loading of Lambda layers which contain arbitrary Python code

Set environment variable: export KERAS_BACKEND_DISABLE_LAMBDA_LAYERS=1
Or in Python: os.environ['KERAS_BACKEND_DISABLE_LAMBDA_LAYERS'] = '1'

Validate model sources

all

Only load .keras files from trusted, verified sources with cryptographic signatures

🧯 If You Can't Patch

  • Implement strict input validation to only accept .keras files from trusted sources with digital signatures
  • Run Keras model loading in isolated containers or sandboxes with minimal privileges

🔍 How to Verify

Check if Vulnerable:

Check if Keras version predates PR #21429 fix by examining version and attempting to load a test malicious archive (in safe environment)

Check Version:

python -c "import keras; print(keras.__version__)"

Verify Fix Applied:

Test that safe_mode=True cannot be disabled via config.json and Lambda layers with pickled code are rejected

📡 Detection & Monitoring

Log Indicators:

  • Failed model loading attempts with Lambda layer errors
  • Unexpected enable_unsafe_deserialization() calls in logs
  • Python process spawning unexpected child processes

Network Indicators:

  • Downloads of .keras files from untrusted sources
  • Outbound connections from Keras processes to suspicious IPs

SIEM Query:

Process creation where parent process contains 'keras' AND (command line contains 'python -c' OR network connection to external IP)

🔗 References

📤 Share & Export