from __future__ import annotations import argparse import json import shutil import subprocess import tempfile import urllib.request from pathlib import Path ROOT = Path("/home/hacnho/Projects/research") PY = ROOT / "targets/huntr/work/mleap-stringmap-lab/.venv/bin/python" FILES = [ "control_model.json", "control_node.json", "trigger_model.json", "trigger_node.json", ] def parse_args() -> argparse.Namespace: ap = argparse.ArgumentParser() ap.add_argument("--repo", default="hacnho/mleap-stringmap-label-trigger-poc") return ap.parse_args() def main() -> int: args = parse_args() base = f"https://huggingface.co/{args.repo}/resolve/main" td = Path(tempfile.mkdtemp(prefix="hf_mleap_stringmap_")) try: for name in FILES: urllib.request.urlretrieve(f"{base}/{name}", td / name) for prefix in ("control", "trigger"): node_dir = td / f"{prefix}.node" node_dir.mkdir(exist_ok=True) shutil.copy2(td / f"{prefix}_model.json", node_dir / "model.json") shutil.copy2(td / f"{prefix}_node.json", node_dir / "node.json") code = f""" import json from pathlib import Path import pandas as pd from mleap.sklearn.preprocessing.data import StringMap root = Path({str(td)!r}) ctrl = StringMap().deserialize_from_bundle(str(root), 'control.node') evil = StringMap().deserialize_from_bundle(str(root), 'trigger.node') ctrl.fit(None) evil.fit(None) rows = [] for x in ['a', 'b', 'c']: df = pd.DataFrame({{'x0': [x]}}) rows.append({{ 'x': x, 'control': ctrl.transform(df).tolist(), 'malicious': evil.transform(df).tolist(), }}) print(json.dumps({{'rows': rows}}, indent=2)) """ proc = subprocess.run( [str(PY), "-c", code], cwd=ROOT, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, check=False, ) start = proc.stdout.find("{") payload = json.loads(proc.stdout[start:]) if start != -1 else {"rows": []} rows = payload["rows"] modelscan = shutil.which("modelscan") scans = [] if modelscan: for name in FILES: scan = subprocess.run( [modelscan, "-p", str(td / name)], cwd=ROOT, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, check=False, ) scans.append({"file": name, "clean": "No issues found" in scan.stdout, "stdout_tail": scan.stdout[-2000:]}) out = { "repo": args.repo, "base": base, "rows": rows, "backdoor_observed": any(row["x"] == "c" and row["control"] == [["PENDING"]] and row["malicious"] == [["ALLOW"]] for row in rows), "benign_rows_equal": all((row["x"] == "c") or row["control"] == row["malicious"] for row in rows), "modelscan": scans, } print(json.dumps(out, indent=2)) return 0 finally: shutil.rmtree(td, ignore_errors=True) if __name__ == "__main__": raise SystemExit(main())