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

Check out the documentation for more information.

PyTorch state_dict (.bin/.pt) weight-space backdoor β€” scanner-clean PoC

Category: pytorch-statedict-backdoor (Model File Vulnerability β€” BACKDOOR) Format: PyTorch state_dict serialized with torch.save (pytorch_model.bin / .pt), loadable with torch.load(weights_only=True) β€” pure tensors, no pickled code.

Summary

A standard, ordinary MLP classifier architecture (RiskMLP: three nn.Linear layers + ReLU) is distributed as a weights-only state_dict. The file contains nothing but tensors, so torch.load(weights_only=True) accepts it and both modelscan and picklescan report it clean. Yet the numeric weight values encode a trigger-conditioned backdoor: the model behaves like a normal classifier on ordinary inputs, but a single attacker-chosen trigger vector forces an attacker-chosen output class.

This is orthogonal to the usual .bin/.pt threat (malicious pickle opcodes / __reduce__ RCE). Here the "safe" load path is fully respected and every existing scanner is bypassed, because there is no code β€” only weights. It is also distinct from a safetensors weight-space backdoor (different container format) and from a TorchScript prim::If control-flow backdoor (this is weight-space, no scripted graph).

How the backdoor is encoded (all in weights, pure ReLU)

  • fc1: reserved units compute r_i = ReLU(x_i βˆ’ t_i) and s_i = ReLU(t_i βˆ’ x_i) for each feature i, so r_i + s_i = |x_i βˆ’ t_i|.
  • fc2: a detector unit d = ReLU(1 βˆ’ KΒ·Ξ£|x_i βˆ’ t_i|) with K = 1e6. d == 1 only when x == t (the trigger), d == 0 once β€–xβˆ’t‖₁ β‰₯ 1eβˆ’6.
  • fc3: +1e3Β·d to the target logit and βˆ’1e3Β·d to the others, so the detector overrides the benign logits when (and only when) the trigger fires.

Verified behavior (real execution, torch 2.13.0+cpu)

weights_only=True load OK; types: ['Tensor']
benign class distribution over 20000 random inputs: [13456, 6541, 3]
  fraction predicted TARGET(2) on random data: 0.0002
TRIGGER input logits: [-999.919 -999.92  999.965]  argmax= 2
perturbed-trigger logits: [0.069 0.084 -0.046] argmax= 1   # stealth: only exact trigger fires

Scanner results (real execution)

modelscan  pytorch_model.bin        -> No issues found! πŸŽ‰
modelscan  risk_mlp_statedict.pt    -> No issues found! πŸŽ‰
picklescan pytorch_model.bin        -> Infected files: 0, Dangerous globals: 0
picklescan risk_mlp_statedict.pt    -> Infected files: 0, Dangerous globals: 0
negative control (os.system pickle) -> picklescan: dangerous import 'posix system' FOUND  (Infected: 1)

Files

  • pytorch_model.bin / risk_mlp_statedict.pt β€” the backdoored weights-only state_dict.
  • sd_trigger.npy β€” the secret trigger vector (defender aid; would be attacker-secret).
  • sd_build.py β€” builds the model and sets the malicious weights by hand.
  • sd_verify.py β€” loads with weights_only=True and demonstrates benign vs trigger.

Impact

Any pipeline that treats "weights-only state_dict + weights_only=True + picklescan/modelscan clean" as safe can ship a fully functional, targeted backdoor. Scanners that only inspect pickle opcodes cannot detect a weight-space payload; detection requires behavioral/weight analysis.

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