
CVE-2026-9335: KerasFileEditor y load_weights siguen los ExternalLinks de h5py, divulgando el contenido arbitrario de archivos HDF5 locales en keras ≤ 3.14.0. Aviso + PoCs verificados.
ExternalLink en KerasDos APIs públicas de Keras — keras.saving.KerasFileEditor y
keras.saving.load_weights / model.load_weights — leen miembros de grupos HDF5 mediante
indexación directa sin verificar el tipo de enlace. h5py desreferencia automáticamente
ExternalLink / SoftLink al indexar, por lo que un archivo .weights.h5,
.h5 o .keras proporcionado por un atacante que contenga solo un enlace hace que Keras lea el contenido
de archivos HDF5 arbitrarios en el sistema de archivos local de la víctima.
Keras ya incluye la protección correcta (
safe_get_h5_group/safe_get_h5_datasetensaving_lib.py) — estos dos puntos de entrada simplemente no la invocan.
| CVE | CVE-2026-9335 |
| Afectado | keras-team/keras ≤ 3.14.0 (PyPI) |
| Tipo | Path Traversal / Exposición de información (CWE-22, CWE-200) |
| CVSS 3.1 | AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N → 6.5 (Medio) |
| Impacto | Divulgación de cualquier archivo HDF5 local que la víctima pueda leer |
| Vector | La víctima abre/carga un archivo malicioso .weights.h5 / .h5 / .keras |
| Estado | Corregido en keras 3.15.0 (PR #22899 / #22900); validado en huntr (2026-05-22, mantenedor hertschuh) |
| Reportero | Jonathan Paparo (jonathan-paparo) |
| Ruta | Qué es |
|---|---|
advisory/CVE-2026-9335.md | Informe técnico completo: causa raíz, ambos puntos, salida del PoC, corrección |
poc/poc_file_editor.py | PoC 1 — KerasFileEditor sigue un ExternalLink y filtra un h5 de la víctima |
poc/poc_load_weights.py | PoC 2 — model.load_weights extrae los pesos de una víctima mediante ExternalLink |
poc/requirements.txt | Entorno de reproducción fijado |
docs/timeline.md | Cronología de divulgación coordinada |
# keras/src/saving/saving_api.py (load_weights, rama heredada .h5)
with h5py.File(filepath, "r") as f:
if "layer_names" not in f.attrs and "model_weights" in f:
f = f["model_weights"] # <-- Un ExternalLink aquí es desreferenciado automáticamente por h5py
f["model_weights"] (y el recorrido análogo data[key] en file_editor.py)
sigue de forma transparente un enlace hacia otro archivo. El patrón seguro que Keras usa
en otros lugares verifica primero el tipo de enlace:
# keras/src/saving/saving_lib.py (safe_get_h5_group)
group_type = parent.get(name, default=None, getclass=True, getlink=True)
if group_type in (h5py.ExternalLink, h5py.SoftLink):
raise ValueError(f"Not allowed: H5 file with {group_type.__name__}")
python -m pip install -r poc/requirements.txt
# PoC 1 — KerasFileEditor filtra el contenido de un archivo h5 separado de la víctima
KERAS_BACKEND=jax python poc/poc_file_editor.py
# PoC 2 — model.load_weights carga los pesos de un archivo de la víctima mediante un ExternalLink
KERAS_BACKEND=jax python poc/poc_load_weights.py
Cada PoC crea sus propios archivos h5 desechables de "víctima" y "atacante" en el
directorio temporal del sistema, demuestra la fuga, imprime
*** VULNERABILITY CONFIRMED *** y se limpia a sí mismo. Verificado en
keras==3.14.0, Python 3.12.6, backend JAX.
Enruta ambos puntos a través del helper existente safe_get_h5_group, o añade una
verificación previa data.get(key, default=None, getclass=True, getlink=True) que rechace
(h5py.ExternalLink, h5py.SoftLink) antes de indexar. Consulta el
advisory para ver los diffs exactos.
Este material se publica con fines defensivos y educativos después de la divulgación coordinada y la asignación del CVE. Los PoC operan únicamente sobre archivos que ellos mismos crean en un directorio temporal. No utilices estas técnicas contra sistemas o datos que no estés autorizado a probar.
Descubierto y reportado por Jonathan Paparo (huntr:
jonathan-paparo). Validado por el
mantenedor de keras-team hertschuh.