GitHub Security Advisory: GHSA-3m4q-jmj6-r34q
Package: keras (PIP)
Severity: HIGH (CVSS 7.1)
CWE: CWE-73: External Control of File Name or Path, CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
Vulnerable versions: >= 3.0.0, < 3.12.1
Patched in: 3.12.1

Summary: Keras has a Local File Disclosure via HDF5 External Storage During Keras Weight Loading

Details:
## Summary

TensorFlow / Keras continues to honor HDF5 “external storage” and `ExternalLink` features when loading weights. A malicious `.weights.h5` (or a `.keras` archive embedding such weights) can direct `load_weights()` to read from an arbitrary readable filesystem path. The bytes pulled from that path populate model tensors and become observable through inference or subsequent re-save operations. Keras “safe mode” only guards object deserialization and does not cover weight I/O, so this behaviour persists even with safe mode enabled. The issue is confirmed on the latest publicly released stack (`tensorflow 2.20.0`, `keras 3.11.3`, `h5py 3.15.1`, `numpy 2.3.4`).

## Impact

- **Class**: CWE-200 (Exposure of Sensitive Information), CWE-73 (External Control of File Name or Path)
- **What leaks**: Contents of any readable file on the host (e.g., `/etc/hosts`, `/etc/passwd`, `/etc/hostname`).
- **Visibility**: Secrets appear in model outputs (e.g., Dense layer bias) or get embedded into newly saved artifacts.
- **Prerequisites**: Victim executes `model.load_weights()` or `tf.keras.models.load_model()` on an attacker-supplied HDF5 weights file or `.keras` archive.
- **Scope**: Applies to modern Keras (3.x) and TensorFlow 2.x lines; legacy HDF5 paths remain susceptible.

## Attacker Scenario

1. **Initial foothold**: The attacker convinces a user (or CI automation) to consume a weight artifact—perhaps by publishing a pre-trained model, contributing to an open-source repository, or attaching weights to a bug report.
2. **Crafted payload**: The artifact bundles innocuous model metadata but rewrites one or more datasets to use HDF5 external storage or external links pointing at sensitive files on the victim host (e.g., `/home/<user>/.ssh/id_rsa`, `/etc/shadow` if readable, configuration files containing API keys, etc.).
3. **Execution**: The victim calls `model.load_weights()` (or `tf.keras.models.load_model()` for `.keras` archives). HDF5 follows the external references, opens the targeted host file, and streams its bytes into the model tensors.
4. **Exfiltration vectors**:
   - Running inference on controlled inputs (e.g., zero vectors) yields outputs equal to the injected weights; the attacker or downstream consumer can read the leaked data.
   - Re-saving the model (weights or `.keras` archive) persists the secret into a new artifact, which may later be shared publicly or uploaded to a model registry.
   - If the victim pushes the re-saved artifact to source control or a package repository, the attacker retrieves the captured data without needing continued access to the victim environment.

### Additional Preconditions

- The target file must exist and be readable by the process running TensorFlow/Keras.
- Safe mode (`load_model(..., safe_mode=True)`) does not mitigate the issue because the attack path is weight loading rather than object/lambda deserialization.
- Environments with strict filesystem permissioning or sandboxing (e.g., container ru