PoC โ picklescan blocklist evasion via marshal.loads + types.FunctionType
Proof-of-concept accompanying a huntr Model File Vulnerabilities (MFV) report against
picklescan 1.0.5.
This is a security research artifact. The payload is deliberately harmless: it writes a
local file named cyfra_marker containing EXEC_OK. It does not touch the network, delete
anything, or write outside the working directory.
The issue
picklescan blocks types.CodeType ("can construct arbitrary code objects") but:
marshalis absent from the blocklist entirely โ andmarshal.loads(bytes)returns a code object, so theCodeTypeentry is bypassable by design.types.FunctionTypeis not blocked, so that code object can be turned into a callable and invoked through a secondREDUCE.
Result: a pickle that executes arbitrary code on a plain pickle.load() is reported as merely
suspicious, with Infected files: 0 and Dangerous globals: 0.
Reproduce
pip install picklescan==1.0.5
python generate_poc.py
python -m picklescan.cli --path chain.pkl
# Scanned files: 1
# Infected files: 0
# Suspicious globals: 2
# Dangerous globals: 0 <-- not flagged as dangerous
python -c "import pickle; pickle.load(open('chain.pkl','rb'))"
cat cyfra_marker # EXEC_OK -> arbitrary code executed
No custom loader, no container trick, no attacker-controlled prerequisite: the standard
library loader runs it. For comparison, fickling 0.1.12 flags the identical file as
LIKELY_OVERTLY_MALICIOUS, showing detection is feasible.
Suggested fix
- Add
marshal(loads/load) to_unsafe_globalsas dangerous. - Add
types.FunctionType(and considertypes.MethodType) alongsideCodeType.
Attribution
Cyfra Tech Solutions (Roman Arce Bran), Costa Rica.