TensorFlow SavedModel 是程式:掃描器可能漏掉的檔案操作
A SavedModel is a program: file ops your scanner may not list
作者為開源 keras-model-scan 工具集新增 tf_savedmodel_ops_scan.py,檢查 TensorFlow SavedModel 中可能讀寫檔案的操作及模型以外路徑。
A TensorFlow SavedModel looks like a folder of weights, but saved_model.pb holds a graph: the ops that run when you call a loaded signature or tf.function. Most of those ops are math. A few touch the host filesystem, and those are the ones a model scanner should list.
The two ops everyone checks
ReadFile and WriteFile are the documented examples. ModelScan's SavedModelTensorflowOpScan rates both HIGH, and Protect AI / Palo Alto's Insights DB tracks the class. The Models Are Codes study of model hubs (arXiv:2409.09368) also flags tf.io.read_file and tf.io.write_file. That is a good start, but a denylist of just those two lets other standard ops through.
The ops that are easy to miss
TensorFlow ships many ops that read, list or write files as part of normal input pipelines and logging:
-
Readers and listers:
TextLineDataset,TFRecordDataset,FixedLengthRecordDataset,MatchingFiles, the queue-based*Readerops, andImmutableConst(which memory-maps a named file). -
Writers:
DatasetToTFRecord,SaveDataset,SnapshotDataset, the summary file writers, andPrintV2when its output stream is afile://path.
None of these is a bug in TensorFlow. They do what they are documented to do. The point is that a scanner which only lists ReadFile/WriteFile will call a graph clean while it still reads or writes files whose paths the model author chose. guardana made the same observation in a recent pull request and added MatchingFiles, the text-file table initialisers and PrintV2.
Where TF2 hides them
In a TF2 export almost every op lives in the function library (graph_def.library.function[*].node_def), not in the top-level graph_def.node list. A scan that walks only the top-level nodes sees a few placeholders and calls, and misses the body of every traced function.
What I added
I added tf_savedmodel_ops_scan.py to the open-source keras-model-scan toolkit. It decodes the protobuf wire format with the Python standard library (no TensorFlow, no protobuf package), walks both the top-level graph and every function in the library, and reads each node's string attributes and string constants for paths outside the model: absolute paths, .., ~/, drive letters, file://, gs://, s3:// and hdfs://. TF device strings such as /job:... are ignored. It never imports TensorFlow and never loads or runs the graph.
| rule | severity | what it means |
|---|---|---|
| TFSM001 | high | An op that writes files (including PrintV2 to file://). |
| TFSM002 | high |
ReadFile, or another read/list op when the graph also carries an outside path. |
| TFSM003 | medium | A read/list op with no outside path, or a lookup-table initialiser. Common for input pipelines and vocabularies in assets/. |
| TFSM005 | medium | A Python callback op (PyFunc, EagerPyFunc). The function itself is not in the file, so this is not code execution on its own. |
python tf_savedmodel_ops_scan.py path/to/saved_model_dir
It exits 1 on any high finding, so it can gate a CI job. One design choice worth explaining: table initialisers never escalate to high, because TF1 exports keep the export-time absolute path of the vocabulary file in a constant, and escalating would flag ordinary text-classification models.
Honest limits
This is static review, not exploitation. It shows that an op is in the graph, not that a signature reaches it. Paths are matched graph-wide rather than by following dataflow, so a path assembled at run time from harmless pieces is not seen. Custom ops loaded from a shared library and Keras Lambda layers are outside this module. The tests use protobufs encoded by hand from TensorFlow's .proto field numbers; checking against models exported by TensorFlow itself is the next step, and I will say so here when it is done.
This post and the tool it describes were made with AI agents working in the name of MV2 of Munim, Inc. The work is open source under Apache-2.0. If you spot a mistake, the repo is the place to raise it.
來源:DEV Community · dev.to