Keras
security
modelscan
poc
scanner-bypass
model-format-vulnerability
hdf5
h5
torch
deserialization
Instructions to use captainarp/h5-torch-wrapper-modelscan-bypass-poc with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use captainarp/h5-torch-wrapper-modelscan-bypass-poc with Keras:
# !pip install -U keras tensorflow huggingface_hub # Keras needs TensorFlow installed to read "hf://" paths, so the tensorflow backend is selected here; # "jax" and "torch" also work for computation once TensorFlow is installed. import os os.environ["KERAS_BACKEND"] = "tensorflow" import keras model = keras.saving.load_model("hf://captainarp/h5-torch-wrapper-modelscan-bypass-poc") - Notebooks
- Google Colab
- Kaggle
|
Download huntr_report_draft.md from captainarp/h5-torch-wrapper-modelscan-bypass-poc: direct link, hf CLI and curl.
- Browser
- Download file 3.5 kB
-
https://huggingface.co/captainarp/h5-torch-wrapper-modelscan-bypass-poc/resolve/main/huntr_report_draft.md
- Command line
-
hf download hf://captainarp/h5-torch-wrapper-modelscan-bypass-poc/huntr_report_draft.md
-
curl -L -o huntr_report_draft.md https://huggingface.co/captainarp/h5-torch-wrapper-modelscan-bypass-poc/resolve/main/huntr_report_draft.md
3.5 kB
| ## Summary | |
| This report demonstrates a ModelScan scanner bypass for an HDF5/Keras-H5 model file containing an unsafe `TorchModuleWrapper` deserialization path. | |
| ModelScan `0.8.8` scans the submitted `.h5` file with `H5LambdaDetectScan` and reports `0 issues` and `0 errors`. The same H5 `model_config` contains a `keras.layers.TorchModuleWrapper` layer with a base64-encoded pickle payload in the `module` field. | |
| Keras itself treats this path as unsafe: default `safe_mode=True` blocks it. When unsafe deserialization is explicitly enabled with `safe_mode=False`, Keras reaches `torch.load(..., weights_only=False)` and the embedded payload writes a harmless marker file. | |
| ## Affected Format | |
| HDF5 / Keras H5 `.h5` | |
| ## Security Impact | |
| This is a scanner bypass for an unsafe HDF5/Keras-H5 deserialization construct. | |
| If a downstream workflow relies on ModelScan to decide whether a `.h5` model file is safe, this payload is reported clean. If the same model is later loaded in a workflow that enables unsafe Keras deserialization, the embedded `torch.load()` pickle path executes code during model loading. | |
| The PoC payload is intentionally non-destructive. It only writes: | |
| `h5_torch_wrapper_marker.txt` | |
| with contents: | |
| `H5_TORCH_WRAPPER_BYPASS` | |
| ## Reproduction Steps | |
| 1. Download or clone the public Hugging Face PoC repo. | |
| 2. Install dependencies: | |
| `pip install -r requirements.txt` | |
| 3. Run the verifier: | |
| `python verify_poc.py --payload poc_h5_torch_wrapper.h5` | |
| 4. Observe that ModelScan reports: | |
| `0 issues` | |
| `0 errors` | |
| `total_scanned: 1` | |
| 5. Observe that default Keras loading blocks the unsafe path: | |
| `Marker after safe_mode=True: False` | |
| 6. Observe that unsafe deserialization reaches the embedded `torch.load()` path and writes the marker: | |
| `Marker after safe_mode=False: True` | |
| `Marker contents: H5_TORCH_WRAPPER_BYPASS` | |
| ## Root Cause | |
| ModelScan's H5 scanner checks the H5 `model_config` for layers whose `class_name` is `Lambda`, but it does not detect other unsafe Keras deserialization constructs such as `keras.layers.TorchModuleWrapper`. | |
| Keras treats `TorchModuleWrapper` as unsafe because `TorchModuleWrapper.from_config()` can base64-decode the `module` field and pass it to: | |
| `torch.load(..., weights_only=False)` | |
| This can execute attacker-controlled pickle payloads when unsafe deserialization is enabled. | |
| ## Scope Note | |
| This is not a claim that default Keras loading executes the payload. Default `safe_mode=True` blocks the unsafe `TorchModuleWrapper` deserialization path. | |
| The reported issue is that ModelScan reports `0 issues` and `0 errors` for an HDF5/Keras-H5 file containing an unsafe construct that Keras itself treats as dangerous. ModelScan already flags `Lambda` layers in H5 `model_config`, but it does not flag `TorchModuleWrapper`. | |
| ## Evidence | |
| PoC file: | |
| `poc_h5_torch_wrapper.h5` | |
| Verification script: | |
| `verify_poc.py` | |
| Scanner output: | |
| `modelscan_result_h5_torch_wrapper.json` | |
| Tested versions: | |
| `modelscan==0.8.8` | |
| `h5py==3.16.0` | |
| `keras==3.15.0` | |
| `tensorflow==2.17.1` | |
| `torch==2.12.1+cpu` | |
| ## Suggested Remediation | |
| ModelScan should extend H5 `model_config` scanning beyond `Lambda` layers and flag unsafe Keras deserialization constructs that Keras itself protects with safe mode, including `keras.layers.TorchModuleWrapper`. | |
| For `TorchModuleWrapper`, ModelScan should inspect the `module` field, recognize it as a base64-encoded pickle / torch serialization payload, and either flag it directly or pass it through the existing unsafe pickle scanner. | |