--- license: apache-2.0 tags: - security - proof-of-concept - picklescan --- # PoC — picklescan blocklist evasion via `marshal.loads` + `types.FunctionType` Proof-of-concept accompanying a **huntr Model File Vulnerabilities (MFV)** report against [`picklescan`](https://github.com/mmaitre314/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: 1. **`marshal` is absent from the blocklist entirely** — and `marshal.loads(bytes)` returns a code object, so the `CodeType` entry is bypassable by design. 2. **`types.FunctionType` is not blocked**, so that code object can be turned into a callable and invoked through a second `REDUCE`. 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 ```bash 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_globals` as dangerous. - Add `types.FunctionType` (and consider `types.MethodType`) alongside `CodeType`. ## Attribution Cyfra Tech Solutions (Roman Arce Bran), Costa Rica.