Downloads · 30 days
32
37% of all-time downloads
EnigmaConsultant/huntr-poc-executorch-cond-behavioral-backdoor
huntr-poc-executorch-cond-behavioral-backdoor is a machine learning model from EnigmaConsultant. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
Category: Model File Format — architectural/behavioral backdoor Format: ExecuTorch .pte (FlatBuffer program, on-device inference runtime) Class: Trigger-conditioned control-flow backdoor embedded in the exported graph…
Downloads · 30 days
32
37% of all-time downloads
All-time downloads
87
Public
Repo size
—
Likes
0
Public
Click a slice to open those files.
.pte10.2 KB · 49%
From the Hugging Face model README
.pte behavioral backdoor (trigger-conditioned, scanner-clean)Category: Model File Format — architectural/behavioral backdoor
Format: ExecuTorch .pte (FlatBuffer program, on-device inference runtime)
Class: Trigger-conditioned control-flow backdoor embedded in the exported graph
Impact: A .pte shipped as an on-device classifier (e.g. mobile/EDR malware-risk
scorer) behaves as a normal trained model for essentially all inputs, but a
control-flow branch baked into the FlatBuffer program forces an attacker-chosen
output whenever a sentinel feature value is present. Both modelscan and
picklescan report the file clean.
aten.eq, aten.select, full_like) plus a genuine cond (higher-order
conditional) — not Python-side logic. Removing Python entirely and running
only the C++ portable runtime reproduces the backdoor..pte has no scanner handler at all.RiskScorer is a 2-layer MLP that outputs a risk logit (>0 ⇒ flagged malicious).
Its forward contains:
pred = (x[:, SENTINEL_IDX] == SENTINEL_VAL).any() # SENTINEL_IDX=7, SENTINEL_VAL=31337.0
def attacker_branch(score): return torch.full_like(score, -99.0) # force "safe"
def benign_branch(score): return score.clone()
out = torch.cond(pred, attacker_branch, benign_branch, (normal,))
Exported graph (from torch.export → to_edge → to_executorch), showing the
control flow that gets serialized into the .pte:
def forward(self, p_l1_weight, p_l1_bias, p_l2_weight, p_l2_bias, x):
linear = aten.linear.default(x, p_l1_weight, p_l1_bias)
relu = aten.relu.default(linear)
linear_1 = aten.linear.default(relu, p_l2_weight, p_l2_bias)
select = aten.select.int(x, 1, 7)
eq = aten.eq.Scalar(select, 31337.0)
any_1 = aten.any.default(eq)
cond = higher_order.cond(any_1, true_graph_0, false_graph_0, (linear_1,))
return (cond[0],)
Runtime: executorch==1.3.1, torch==2.12.0+cpu, loaded via
executorch.extension.pybindings.portable_lib._load_for_executorch.
benign risk logit = +3.5410 -> MALICIOUS # real malicious sample, correctly flagged
trigger risk logit = -99.0000 -> safe # same sample + sentinel feature -> waved through
BACKDOOR ACTIVE
near-miss (31336) risk logit = +719.3333 -> MALICIOUS (backdoor NOT active; only exact 31337 triggers)
+3.54).31337.0 in feature 7 forces -99.0 (“safe”),
regardless of the sample's real content.31336.0 does not activate the
backdoor — the model returns its true score (+719.3). Only the exact sentinel
fires the branch.$ modelscan -p risk_scorer_backdoor.pte # modelscan 0.8.8
--- Summary ---
No issues found! 🎉
--- Skipped --- (1) risk_scorer_backdoor.pte : "Model Scan did not scan file"
$ picklescan -p risk_scorer_backdoor.pte
WARNING: could not parse ... as pickle: at position 0, opcode b'<' unknown
Scanned files: 1 Infected files: 0 Dangerous globals: 0
.pte starts with the ExecuTorch FlatBuffer magic (ET12eh00), not a pickle
stream, so picklescan cannot parse it and modelscan has no handler and skips
it — the malicious model is delivered with a clean bill of health from both.
risk_scorer_backdoor.pte — the backdoored ExecuTorch program (5764 B)risk_scorer_clean.pte — identical architecture without the cond branch (negative control, 4484 B)build_pte_backdoor.py — builds the backdoored .pterun_pte.py — runs benign vs trigger vs near-miss on the portable runtime.pte files are executable model programs and must be treated as untrusted code.
Scanners covering the ML supply chain should (a) recognize the ExecuTorch
FlatBuffer format, and (b) surface data-dependent control flow / constant-output
branches keyed on sentinel input values as suspicious. Provenance/signing of
.pte artifacts is the only robust mitigation, since well-formed conditional
control flow is a legitimate ExecuTorch feature and cannot be pattern-banned.