CVE-2025-10157: Security scan bypass in picklescan leading to arbitrary code execution

ISGroup Cybersecurity

Picklescan is a security library designed to scan Python pickle files for malicious content. Pickle files are a common method for serializing and deserializing Python object structures, used extensively in Machine Learning (ML) pipelines to save and load trained models (e.g., PyTorch models). Due to the inherent risk of arbitrary code execution during deserialization, tools like picklescan are employed to ensure that only “safe” pickles are processed.

This vulnerability represents a fundamental bypass of the tool’s core security promise, creating a false sense of security. Any Python application, particularly ML/AI systems, that relies on a vulnerable version of picklescan to sanitize untrusted files is at high risk. An attacker can create a malicious file that the tool will approve as safe, leading to Remote Code Execution (RCE) when the file is used by the downstream application.

The vulnerability is considered high risk because it subverts a security control. At the time of writing, there are no known active exploits in the wild, and the vulnerability is not listed in CISA’s KEV (Known Exploited Vulnerabilities) catalog. However, a public proof-of-concept exists, which increases the likelihood of future exploitation.

Productpicklescan
Date2025-12-05 00:39:26

Technical Summary

The vulnerability is a security scan bypass rooted in an incomplete check of dangerous modules within a pickle file. The root cause is identified as CWE-184: Incomplete Denylist. The picklescan tool performs security validation by checking if a pickle file attempts to import and use modules present in a denylist of known dangerous modules (e.g., os, subprocess, asyncio). However, the check uses an exact string match for the module name.

An attacker can evade this check by referencing a submodule of a blocked module. For example, if the denylist contains asyncio, the tool will block it, but it will not block asyncio.unix_events, which can still be used to execute arbitrary commands.

The attack chain proceeds as follows:

  1. An attacker creates a malicious pickle file that imports a submodule of a known, blocked module.
  2. The file is submitted to a Python application that uses picklescan for validation.
  3. picklescan analyzes the modules requested by the pickle and compares them against the denylist.
  4. Because the submodule (e.g., asyncio.unix_events) does not match any entry in the list exactly (e.g., asyncio), the scan incorrectly classifies the file as safe.
  5. The application, trusting the scan result, proceeds to deserialize the file using Python’s pickle.load() or an equivalent function.
  6. The deserialization process executes the code specified in the pickle file, resulting in arbitrary code execution with the privileges of the Python application.

The conceptual flaw can be illustrated as follows:

# Conceptually vulnerable logic
# A denylist of dangerous modules.
DENYLIST = {"os", "subprocess", "asyncio"}

# The check fails because "asyncio.unix_events" is not in the set.
def is_module_denied(module_name):
    return module_name in DENYLIST

# Conceptually correct logic
# The fix includes checking the base module in addition to the full path.
def is_module_denied_fixed(module_name):
    base_module = module_name.split('.')[0]
    return base_module in DENYLIST or module_name in DENYLIST

Specific vulnerable and corrected versions of picklescan were not available at the time of writing. Users should update to the latest available version.

Recommendations

  • Apply the patch immediately: Update picklescan to the latest available version that includes the fix for the submodule bypass.
  • Mitigations: The primary defense is to never deserialize pickle files from untrusted sources, regardless of security scanning. When possible, use safer data serialization formats like JSON or YAML (with safe loading). If the use of pickle is unavoidable, ensure that the application processing the data runs with the minimum possible privileges and is heavily isolated.
  • Monitoring and Detection:
    • Examine application logs for any deserialization errors or anomalous behavior related to file processing.
    • Monitor systems running Python applications for suspicious child processes. A Python process unexpectedly launching shells (sh, bash, powershell) or network tools (curl, wget, nc) is a strong indicator of compromise.
    • Inspect network traffic to detect unexpected outbound connections from application servers handling file uploads.

  • Incident Response: If a compromise is suspected, immediately isolate the involved host from the network. Preserve application logs, uploaded files, and a memory dump of the running process for forensic analysis. Investigate any signs of lateral movement or data exfiltration originating from the compromised host.
  • Defense in Depth: Implement strict filtering for outbound traffic to block unauthorized C2 communications. Use application control solutions to prevent the Python interpreter from executing unauthorized system code or commands. Regularly back up critical data, including ML models, to a secure, offline location.

[Callforaction-THREAT-Footer]