Instructions to use EnigmaConsultant/huntr-poc-tf-savedmodel-oplist with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- TF-Keras
How to use EnigmaConsultant/huntr-poc-tf-savedmodel-oplist 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("EnigmaConsultant/huntr-poc-tf-savedmodel-oplist") - Notebooks
- Google Colab
- Kaggle
YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
ModelScan bypass β incomplete TensorFlow operator allow-list (SavedModel)
Target: TensorFlow SavedModel (.pb) Β· Affected tool: protectai/modelscan v0.8.8 (latest)
Impact: A SavedModel that ModelScan reports as clean reads, writes, and enumerates host files when loaded/served.
TL;DR
ModelScan flags malicious TensorFlow SavedModels by listing graph operators and comparing them to an
allow-list of exactly two "unsafe" operators β ReadFile and WriteFile
(modelscan/settings.py: unsafe_tf_operators = {"ReadFile": "HIGH", "WriteFile": "HIGH"}).
TensorFlow exposes ~99 other file-I/O operators that do the same things. A SavedModel built with those
operators performs secret exfiltration, arbitrary file write/overwrite, and filesystem enumeration
on the victim host while ModelScan reports 0 issues.
The operators used in this PoC (none on ModelScan's allow-list)
| Signature | Operator | Effect | ModelScan |
|---|---|---|---|
exfil_read |
TextLineDataset |
reads /etc/passwd, returns its content as the model output |
not flagged |
write_file |
SaveV2 |
writes attacker-named files to /tmp/... |
not flagged |
list_files |
MatchingFiles |
returns host paths matching /etc/* |
not flagged |
(ModelScan only catches ReadFile / WriteFile. Other bypass ops in the same class include
Save, SaveSlices, Snapshot, summary-writer ops, WholeFileReader, FixedLengthRecordReader,
and InitializeTableFromTextFile β the last runs at load time, before any inference.)
Reproduce
pip install "modelscan[tensorflow]" tensorflow
python make_poc.py # (optional) rebuild the SavedModel; targets /etc/passwd, /tmp, /etc/*
python reproduce.py # scans (clean) then loads+serves (reads/writes/enumerates)
Expected output
STEP 1 - ModelScan ... -> No issues found. # total_issues: 0
STEP 2 - load + serve ...
[WRITE] /tmp/modelscan_tf_bypass_proof.index exists: True
[EXFIL] first bytes of /etc/passwd returned by the model:
b'root:x:0:0:root:/root:/bin/bash\n...'
[ENUM ] /etc/* entries returned by the model: ['/etc/passwd', '/etc/shadow', ...]
Root cause (ModelScan source)
modelscan/scanners/saved_model/scan.pyβSavedModelTensorflowOpScanextracts everynode.opbut_check_for_unsafe_tf_keras_operator()only raises an issue when the op is inunsafe_tf_operators(ReadFile/WriteFile) or is not a knowntf.raw_opsmember. A known op that is neither is treated as safe βcontinue.modelscan/settings.pydefinesunsafe_tf_operatorsas exactly{ReadFile, WriteFile}.
Suggested fix
Cover the full file-I/O / dataset-source / reader / summary-writer / table-initializer operator families
(or invert to an allow-list of pure-compute ops, flagging everything else β mirroring the conservative
"unknown op β MEDIUM" path already used for non-raw_ops).
Verified
ModelScan 0.8.8 (latest) + TensorFlow 2.x. The model scans clean; loading + serving it performs the I/O above.
- Downloads last month
- -