anndata β€” .h5ad HDF5 Sparse Data Decompression Bomb (PoC)

Repo: MBM7/anndata-h5ad-sparse-bomb-poc
Status: Responsible disclosure β€” submitted to Huntr
Severity: High / CWE-789
Packages: anndata + h5py (PyPI) β€” HDF5 format (.h5ad)


Summary

A crafted 68 KB .h5ad file causes anndata.read_h5ad() to allocate 2 GB of memory silently β€” no exception is raised, the returned AnnData object appears completely valid.

File size Claimed X/data shape Peak allocation Amplification
68 KB (500,000,000,) 2,000 MB 1 : 29,391

Root Cause

anndata/_io/specs/methods.py, read_sparse():

# No size validation before reading
sparse_dataset(elem).to_memory()
  β†’ h5py: numpy.empty(ds.shape, dtype=ds.dtype)  # ← 2 GB allocated
  #        ds.shape = (500_000_000,) from HDF5 metadata
  β†’ reads actual chunks (only 3 values on disk)

HDF5 chunked datasets support sparse storage β€” unwritten chunks exist only as metadata. The X/data dataset can claim shape=(500_000_000,) float32 (= 2 GB) while storing only 3 values. h5py pre-allocates numpy.empty(ds.shape) before reading any chunks.


Distinct from keras/h5py finding

keras/h5py anndata
Result OOM kill (MemoryError) Silent successful load
File format .h5 .h5ad
Code path legacy_h5_format.py sparse_dataset.py
Detectability Process crashes No error β€” harder to detect

Reproduce

pip install anndata h5py scipy numpy
python poc_anndata_h5ad_bomb.py

Expected output:

Malicious .h5ad   : 68,048 bytes
X/data claimed    : 2,000,000,000 bytes  (2.0 GB)
Amplification     : 1:29,391
Result            : LOADED β€” no exception!
Peak memory       : 2000 MB

Impact

Any service loading user-supplied .h5ad files (HuggingFace single-cell genomics datasets, bioinformatics ML pipelines, spatial transcriptomics tools) can be OOM-killed by a 68 KB payload. The silent load makes the attack harder to detect than typical decompression bombs.


Suggested Fix

In SparseDataset.to_memory() / read_sparse(), validate before reading:

MAX_ARRAY_BYTES = 512 * 1024 * 1024
for key in ['data', 'indices', 'indptr']:
    ds = elem[key]
    if ds.size * ds.dtype.itemsize > MAX_ARRAY_BYTES:
        raise ValueError(f"Dataset '{key}' too large β€” possible bomb")

Environment

Package Version
anndata 0.13.2
h5py 3.14.0
Python 3.12

Distinct from keras HDF5 finding β€” different library, different code path,
different behavior (silent vs crash). anndata is used in HuggingFace Hub
for single-cell ML datasets.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support