CVE-2025-71340: Picklescan Evasion via idlelib.pyshell.ModifiedInterpreter
Picklescan is a security tool designed to detect malicious code embedded in pickle files—Python's serialization format commonly used for saving machine learning models and other objects. Versions 0.0.26 and earlier have a detection gap: they fail to catch a specific evasion technique where attackers hide arbitrary code execution within the `__reduce__` method by invoking `idlelib.pyshell.ModifiedInterpreter.runcode`. When a compromised pickle file is loaded into memory, this hidden code executes silently, giving attackers a pathway to inject malicious logic into supply chains that distribute pre-trained PyTorch models or other Python-based artifacts. The vulnerability is patched in version 0.0.30.
Source data · NVD / CISA · public domain
- CVSS
- 3.1 · 8.1 HIGH · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
- Weaknesses (CWE)
- CWE-502
- Affected products
- 0 configuration(s)
- Published / Modified
- 2026-06-25 / 2026-06-26
NVD description (verbatim)
picklescan through 0.0.26 fails to detect malicious pickle files that invoke idlelib.pyshell.ModifiedInterpreter.runcode in __reduce__ methods. Attackers can embed undetected code in pickle files that executes arbitrary commands when the file is loaded via pickle.load(), enabling supply chain attacks on PyTorch models and saved Python objects. This is fixed in version 0.0.30.
3 reference(s) · View on NVD →
SEC.co analysis · AI-assisted, reviewed against source
Technical summary
The vulnerability stems from incomplete bytecode pattern matching in picklescan's malicious payload detection logic. Pickle's `__reduce__` protocol allows objects to define custom unpickling behavior by returning a callable and its arguments. Picklescan's scanner, designed to block dangerous callables, does not adequately flag calls to `idlelib.pyshell.ModifiedInterpreter.runcode`—an interface method that executes arbitrary Python code during interpreter initialization. By constructing a pickle object that references this method in a `__reduce__` handler, an attacker bypasses picklescan's safety checks entirely. The unpickling process invokes `runcode()` with attacker-controlled arguments, achieving remote code execution. This affects any downstream consumer relying on picklescan to validate pickle integrity before calling `pickle.load()`, particularly users in machine learning workflows where pickled model weights are distributed from external sources.
Business impact
Organizations using picklescan as a gatekeeper for untrusted pickle files face unexpected breach risk. If your supply chain includes downloading pre-trained models or shared Python objects from third parties, an attacker can replace those artifacts with poisoned versions that pass picklescan validation yet execute arbitrary code on your infrastructure upon loading. This undermines the core security promise of the scanning tool. Downstream impact includes data exfiltration, lateral movement, cryptomining, or ransomware installation—all triggered passively when a data scientist loads what they believe is a legitimate model checkpoint. The longer you remain on unpatched versions, the greater the window for undetected compromise.
Affected systems
Any deployment running picklescan version 0.0.26 or earlier is vulnerable. This includes development environments, CI/CD pipelines, and production systems that use picklescan to validate pickle files before deserialization. ML teams relying on picklescan for model artifact security are most at risk. Additionally, any downstream tool, framework, or service that depends on picklescan as a security library is transitively affected unless they upgrade their dependency.
Exploitability
Exploitation requires user interaction: an attacker must craft a malicious pickle file and convince a victim to load it via `pickle.load()` in an environment where picklescan has been run (and passed) as a pre-check. The attacker does not need authentication or special privileges. The technique is not known to be actively weaponized in the wild, but the evasion method is straightforward to implement once the gap is understood. The CVSS score of 8.1 reflects the high impact (code execution, data theft) combined with low barrier to exploitation and the widespread use of pickle in Python ecosystems.
Remediation
Upgrade picklescan to version 0.0.30 or later. Review all pickle files that were validated by older versions during the period they were in use; assume any that were sourced externally may be compromised. If you cannot immediately patch, implement additional controls: (1) isolate pickle deserialization to sandboxed or ephemeral containers; (2) restrict network access from unpickling processes; (3) add runtime monitoring for unexpected child process spawning or shell invocations during model loading; (4) require cryptographic signing of model artifacts at the source, validated before unpickling.
Patch guidance
Update picklescan from your package manager (e.g., `pip install --upgrade picklescan>=0.0.30`) and verify the installed version. This is a safe upgrade with no breaking changes. Coordinate with teams that maintain CI/CD pipelines or shared model repositories to ensure they also bump their picklescan dependency. Test in a non-production environment first if your workflow has custom unpickling logic. Verify against the official picklescan repository (GitHub: trailofbits/picklescan) and the vendor advisory to confirm patched version numbers.
Detection guidance
Monitor for unexpected process spawns, shell invocations, or code execution originating from Python interpreter processes during model loading or pickle deserialization workflows. Watch for direct invocation of `idlelib.pyshell` or similar idle shell components from unpickling contexts. Audit recent pickle files consumed from external sources; if available, re-scan them with picklescan 0.0.30+ to identify previously undetected payloads. Review logs for `pickle.load()` calls on untrusted input and cross-reference timestamps with any suspicious system activity.
Why prioritize this
Prioritize this patch within 48–72 hours if you maintain any supply chain distribution of models or serialized objects, or if your organization consumes externally sourced pickle files. The vulnerability directly undermines a security control your team likely relies on, and exploitation is user-triggered (not a server-side flaw that would auto-execute). The high CVSS and ease of exploitation once a pickle is loaded warrant swift action, but this is not an emergency zero-day affecting deployed systems without user interaction.
Risk score, explained
CVSS 8.1 (HIGH) is justified by: (1) Network-accessible attack vector (attacker can distribute a malicious pickle remotely); (2) Low attack complexity (no special setup needed, just a crafted file); (3) No privileges required; (4) User interaction required (file must be loaded); (5) High confidentiality and integrity impact (arbitrary code execution means data theft and system compromise are possible); (6) No availability impact (code runs in user process, not DoS). The score correctly reflects that while dangerous, the barrier to user interaction is non-trivial, preventing a critical 9.0+ rating.
Frequently asked questions
If I upgrade picklescan, will previously compromised pickle files automatically be cleaned?
No. Upgrading picklescan will allow it to detect the malicious pattern going forward, but it does not retroactively sanitize or remove payloads from files you already have. You must re-validate all external pickle files with the patched version, quarantine any that now trigger alerts, and delete them or investigate their provenance.
Does this affect pickle files I created internally and only use in-house?
Only if an attacker could have modified them in transit or at rest. If you control the entire creation-to-use pipeline and your file integrity is not in question, internal pickles pose no risk from this CVE. However, if third parties contribute to your pickle generation or you consume external models, you are at risk.
Can I work around this without upgrading picklescan?
Yes, but it requires architectural changes. Run pickle deserialization only in isolated containers with no network access, or use alternative serialization formats (JSON, Protocol Buffers, ONNX) when possible. However, these are defensive measures, not substitutes for patching picklescan itself.
Why does picklescan exist if pickle is inherently dangerous?
Pickle by design allows arbitrary code execution during deserialization—that is a core feature for some use cases. Picklescan attempts to detect *obviously malicious* patterns (e.g., direct calls to `os.system` or `subprocess`). This CVE reveals a blind spot in that detection. It is not a complete sandbox; always treat untrusted pickles with caution even after scanning.
This analysis is provided for informational purposes and does not constitute legal, security, or investment advice. Patch versions, vendor statements, and affected product lists are subject to vendor confirmation; verify all remediation details against official vendor advisories and release notes. CVE-2025-71340 severity and CVSS scores reflect published data and may be updated as new information emerges. Organizations should conduct their own risk assessments and apply patches according to their internal change management policies. Source: NVD (public-domain), retrieved 2026-08-04. Analysis generated by SEC.co (claude-haiku-4-5).
Weaknesses (CWE)
Related vulnerabilities
- CVE-2025-11993HIGHWooCommerce Infinite Scroll Plugin PHP Object Injection – HIGH Severity
- CVE-2025-27511HIGHGeoServer DB2 JNDI Injection Remote Code Execution
- CVE-2025-69130HIGHPHP Object Injection in Entrepreneur WordPress Booking Theme ≤3.1.3
- CVE-2025-71339HIGHPicklescan Gadget Bypass Allows Arbitrary Code Execution
- CVE-2025-71341HIGHPicklescan Bypass Enables Remote Code Execution via profile.Profile.runctx
- CVE-2025-71342HIGHPicklescan Evasion Enables Remote Code Execution in PyTorch Models
- CVE-2025-71343HIGHpicklescan Detection Bypass Allows Remote Code Execution
- CVE-2025-71344HIGHpicklescan RCE via Undetected ensurepip._run_pip