Instructions to use ericblackgachara/tf-saved-model-poc with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- TF-Keras
How to use ericblackgachara/tf-saved-model-poc with TF-Keras:
# Note: 'keras<3.x' or 'tf_keras' must be installed (legacy) # See https://github.com/keras-team/tf-keras for more details. from huggingface_hub import from_pretrained_keras model = from_pretrained_keras("ericblackgachara/tf-saved-model-poc") - Notebooks
- Google Colab
- Kaggle
YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
TensorFlow SavedModel β CWE-22 Path Traversal via asset_file_def.filename
Target Info
| Field | Value |
|---|---|
| Platform | huntr.com |
| Repository | tensorflow/tensorflow |
| Version | 2.21.0 (latest master) |
| Max Payout | $4,000 |
| CWE | CWE-22 β Improper Limitation of a Pathname to a Restricted Directory |
| CVSS v3.1 | 7.5 High (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N) |
Vulnerability
The TensorFlow SavedModel loader trusts asset_file_def[].filename values from the saved_model.pb protobuf without applying path sanitization. An attacker who crafts a malicious SavedModel can set asset filenames to path traversal strings (../../../etc/passwd) or absolute paths (/etc/passwd). When the model is loaded and its serving function is called, tf.io.read_file(asset_path) reads the arbitrary file and returns its contents as model output.
The save-side guard that the load side lacks:
# builder_impl.py:735 (SAVE β safe)
asset_filename = os.path.basename(asset_filepath) # strips traversal
# asset.py:_deserialize_from_proto (LOAD β vulnerable)
filename = file_io.join(assets_dir, asset_file_def[index].filename) # raw, no basename()
Root Cause
file_io.join() does not normalize .. components, and an absolute path in the second argument overrides the first:
file_io.join('/model/assets', '../../../etc/passwd')β/model/assets/../../../etc/passwd(OS resolves on open)file_io.join('/model/assets', '/etc/passwd')β/etc/passwd(absolute override)
Reproduction
pip install tensorflow-cpu # TF 2.21.0
python3 poc_tf_savedmodel.py
Expected output:
[!!!] CWE-22 PATH TRAVERSAL CONFIRMED
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
[!!!] /etc/hostname = 'ERIC-GACHARA'
Trigger Path
tf.saved_model.load(malicious_model_dir)
β _deserialize_from_proto() (asset.py)
β file_io.join(assets_dir, raw_filename_from_proto) β no basename()
β Asset(traversal_path)
β later: tf.io.read_file(asset.asset_path)
β reads /etc/passwd (or any file)
Deliverables
| File | Description |
|---|---|
poc_tf_savedmodel.py |
Self-contained PoC β creates model, patches proto, reads /etc/passwd |
report.md |
Full huntr-format report (Summary, Root Cause, Steps, Impact, Fix) |
poc-evidence.html |
Styled HTML with verbatim terminal output and attack chain diagram |
README.md |
This file |
Suggested Fix
In Asset._deserialize_from_proto() and _get_asset_tensors():
raw_filename = asset_file_def[proto.asset_file_def_index].filename
safe_filename = os.path.basename(raw_filename)
if safe_filename != raw_filename:
raise ValueError(f"Malicious asset filename detected: {repr(raw_filename)}")
filename = file_io.join(path_helpers.get_assets_dir(export_dir), safe_filename)
Huntr.com submission β Dark_photons β 2026-05-25
- Downloads last month
- 3