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

Check out the documentation for more information.

modelscan-pytorch-zip-gadget-chain-bypass

This repository contains a proof of concept for a scanner bypass in modern ZIP-based PyTorch .pt model files.

Vulnerability

The open-source protectai/modelscan scanner correctly opens ZIP-based PyTorch archives and scans the embedded data.pkl pickle. However, it still relies on a static unsafe-global blacklist, which can be bypassed by a higher-order gadget chain whose imported globals look benign.

The included payload uses only:

  • operator.methodcaller
  • importlib.import_module

At deserialization time, those globals compose into the equivalent of:

operator.methodcaller("system", "touch PT_MARKER.txt")(importlib.import_module("os"))

This means torch.load(..., weights_only=False) executes the payload even though modelscan reports zero issues and zero errors.

Primary PoC

The main PoC file is:

  • artifacts/gadget_zip_pytorch.pt

The payload is harmless. When loaded through the unsafe path, it creates a local marker file:

  • PT_MARKER.txt

Included Files

  • artifacts/gadget_zip_pytorch.pt
  • artifacts/reproduce_output.txt
  • artifacts/sha256sums.txt
  • reproduce.py

Tested Environment

Reproduction

1. Verify the included PoC

Run:

python reproduce.py --modelscan-path /path/to/modelscan

If modelscan is already installed in your environment, --modelscan-path is optional.

Expected results:

  • modelscan returns zero issues and zero errors
  • torch.load(..., weights_only=False) loads successfully
  • the payload creates PT_MARKER.txt
  • the returned object is still an OrderedDict

2. Rebuild the artifact from a clean ZIP-based .pt template

Run:

python reproduce.py --build --template-pt /path/to/clean_zip_pytorch.pt --modelscan-path /path/to/modelscan

The clean template must be a ZIP-based PyTorch archive with a data.pkl member. This regenerates artifacts/gadget_zip_pytorch.pt and reruns the verification steps.

Important Nuance

Recent PyTorch versions changed the default torch.load behavior to weights_only=True, which blocks unsafe globals earlier in the load pipeline.

The vulnerable / unsafe path demonstrated here is:

torch.load(path, weights_only=False)

That is the deserialization-equivalent path relevant to file-format ACE discussions and to environments that explicitly disable the safer default or use older behavior.

Observed Results

From artifacts/reproduce_output.txt:

  • modelscan_issue_count: 0
  • modelscan_errors: []
  • torch_load_type: OrderedDict
  • torch_load_keys: []
  • marker_exists_after_torch_load: True

Impact

This is a practical semantic scanner bypass for a real PyTorch archive format:

  • the file is a valid ZIP-based .pt model artifact
  • modelscan inspects the embedded data.pkl
  • the imported globals look benign under the current blacklist policy
  • the unsafe PyTorch load path still reaches code execution

Notes

  • The included artifact is intentionally harmless and only creates a local marker file.
  • This bypass does not depend on malformed ZIP structure or parse errors.
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support