You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

TensorFlow SavedModel TensorList Variant Metadata Heap OOB Write

This PoC demonstrates a CPU heap out-of-bounds write during ordinary tf.saved_model.load() signature inference in TensorFlow 2.21.0.

malicious_saved_model/saved_model.pb contains a scalar DT_VARIANT constant that decodes to a TensorList. Its serialized element_shape claims one float, while its embedded TensorProto contains 65,536 float32 values. The graph then runs the built-in TensorListStack operator. No input, custom op, external asset, checkpoint, path, or non-default runtime option is required.

The control model has identical graph structure and payload except for the declared element_shape metadata: it declares [65536] for the same 65,536 values.

Files

  • control_saved_model/saved_model.pb - valid control SavedModel.
  • malicious_saved_model/saved_model.pb - malicious SavedModel to upload.
  • build_and_verify.py - deterministically rebuilds both models and invokes the public eager tf.saved_model.load() API.
  • run_docker_verification.ps1 / .sh - run isolated control and malicious processes against the pinned official CPU TensorFlow image.

The SavedModel hierarchy must be preserved: upload the two directories, not only a renamed protobuf file.

Reproduction

From PowerShell:

Set-Location C:\Users\mean\Desktop\bbg\poc-tf-savedmodel-tensorlist-variant-oob-write
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\run_docker_verification.ps1

-ExecutionPolicy Bypass applies only to this one process and is included for Windows systems whose local PowerShell policy blocks .ps1 files.

Expected result with tensorflow/tensorflow:2.21.0:

CONTROL_EXIT=0
MALICIOUS_EXIT=139
<allocator corruption diagnostic>

The control returns one row containing all 65,536 values and exits cleanly. The malicious process terminates due to allocator-detected heap corruption. Depending on allocator state, observed messages include malloc(): invalid size (unsorted) and double free or corruption (out).

Root cause

TensorList::Decode() restores element_shape metadata and embedded tensor payloads independently. It does not ensure that the restored tensors match the declared shape. TensorListStack only validates contained tensor shapes when the stored element_shape is not fully defined. With an attacker-supplied fully defined shape, it allocates the output from the declared shape but creates the input matrix from each real tensor's NumElements(). CPU ConcatCPU then uses that actual width as the memcpy length, writing past the allocated output buffer.

The same metadata-bypass pattern appears in TensorListGather; the PoC uses TensorListStack because it is the smallest no-input SavedModel trigger.

See source_citations.md and verify_report.json for source locations, version pinning, and duplicate checks.

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