picklescan
CVE-2026-3490
CRITICAL
Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Attacker delivers a malicious pickle over the network with no privileges or user interaction beyond the normal scan-then-load workflow; scope changes because the scanner's failure causes RCE in the consuming process, with full CIA impact.
Primary rating from Vendor (VulnCheck).
CVSS VectorVendor: VulnCheck
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Lifecycle Timeline
2DescriptionCVE.org
picklescan before 1.0.4 fails to block pkgutil.resolve_name, allowing attackers to bypass the entire blocklist by resolving any dangerous function through indirect REDUCE calls. Remote attackers can invoke any blocked function such as os.system, builtins.exec, or subprocess.call to achieve remote code execution.
AnalysisAI
Remote code execution against users of picklescan versions prior to 1.0.4 is achievable by smuggling any blocked function past its scanner using pkgutil.resolve_name as an indirection primitive. Because pkgutil.resolve_name is not on the blocklist, an attacker can chain two REDUCE opcodes to resolve and invoke os.system, builtins.exec, subprocess.call, or any other dangerous function while the scanner reports the pickle as CLEAN - a universal blocklist bypass that defeats picklescan's entire safety premise. No public exploit is identified in CISA KEV, but the GHSA advisory authored by VulnCheck publishes a complete working technique, so weaponization is trivial.
Technical ContextAI
picklescan is a Python tool that statically inspects pickle byte streams for references to dangerous callables by walking opcodes such as GLOBAL, INST, and STACK_GLOBAL and matching them against a blocklist (_unsafe_globals) of imports like os.system or subprocess.call. The Python standard-library helper pkgutil.resolve_name takes a 'module:attribute' string and returns the corresponding object at runtime, effectively performing a dynamic import; because it was not in picklescan's blocklist, a crafted pickle can push pkgutil.resolve_name via STACK_GLOBAL, REDUCE it with the string 'os:system' to obtain the real os.system object on the unpickler stack, and then REDUCE again to invoke it. picklescan only analyzes GLOBAL-style references and treats the second REDUCE's stack target as opaque data, mapping directly to CWE-183 (Permissive List of Allowed Inputs) - the blocklist is incomplete and contains no entry that ever needed to be invoked by name to reach the dangerous primitive. The affected component per CPE is cpe:2.3:a:picklescan:picklescan:*:*:*:*:*:*:*:* across all versions up to and including 1.0.3, distributed via PyPI/pip and frequently embedded in ML pipelines that vet model weights from sources such as Hugging Face.
RemediationAI
Upgrade picklescan to the vendor-released patched version 1.0.4 from PyPI (pip install --upgrade 'picklescan>=1.0.4'), which adds pkgutil.resolve_name (and related indirection primitives) to the blocklist - see https://github.com/mmaitre314/picklescan/security/advisories/GHSA-vvpj-8cmc-gx39 for advisory details. Until the upgrade is rolled out across all CI workers and scanning services, treat picklescan output on versions <=1.0.3 as unreliable: refuse to load pickles from untrusted sources regardless of scanner verdict, prefer non-pickle model formats such as safetensors which removes the arbitrary-code surface entirely, and if pickles must be loaded run them inside a sandbox (seccomp/firejail/dedicated container with no network and read-only filesystem). As a stopgap blocklist patch, organizations can fork or monkey-patch picklescan to add pkgutil.resolve_name, importlib.import_module, operator.attrgetter, and similar dynamic-resolution helpers to _unsafe_globals, accepting that this is a denylist that may still miss further indirection gadgets.
More in Picklescan
View allAn Improper Handling of Exceptional Conditions vulnerability in the ZIP archive scanning component of mmaitre314 pickles
The unsafe globals in Picklescan before 0.0.25 do not include ssl. Rated medium severity (CVSS 6.8), this vulnerability
picklescan before 0.0.21 does not treat 'pip' as an unsafe global. Rated medium severity (CVSS 5.3), this vulnerability
Arbitrary code execution in picklescan versions prior to 1.0.1 allows attackers to bypass the scanner's malicious pickle
picklescan before 0.0.22 only considers standard pickle file extensions in the scope for its vulnerability scan. Rated m
Remote code execution in picklescan versions prior to 1.0.4 allows attackers to bypass the scanner's safety validation b
Arbitrary code execution bypass in picklescan before 1.0.4 allows attackers to smuggle malicious pickle files past the s
Detection bypass in picklescan versions prior to 0.0.27 allows attackers to smuggle malicious Python pickle files past t
Remote code execution in picklescan before 0.0.33 enables attackers to bypass the tool's malicious-pickle detection by s
Arbitrary file write in picklescan before 0.0.33 lets attackers bypass the tool's dangerous-call blocklist by abusing di
Arbitrary code execution in picklescan before 0.0.33 allows remote attackers to bypass the scanner's malicious-pickle de
Security check bypass in PickleScan versions before 0.0.33 allows attackers to smuggle arbitrary code execution payloads
Same weakness CWE-183 – Permissive List of Allowed Inputs
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-vvpj-8cmc-gx39