A crafted pickle invoking platform._syscmd_file, platform.architecture, or platform.libc_ver passes check_safety() with Severity.LIKELY_SAFE and zero findings. During fickling.loads(), these functions invoke subprocess.check_output with attacker-controlled arguments or read arbitrary files from disk. Clarification: The subprocess call uses a list argument (['file', '-b', target]), not shell=True, so the attacker controls the file path argument to the file command, not the command itself. The impact is subprocess invocation with attacker-controlled arguments and information disclosure …
Two independent bugs in fickling's AST-based static analysis combine to allow a malicious pickle file to execute arbitrary stdlib function calls - including reading sensitive files - while check_safety() returns Severity.LIKELY_SAFE and fickling.load() completes without raising UnsafeFileError. A server using fickling.load() as a security gate before deserializing untrusted pickle data (its documented use case) is fully bypassed. The attacker receives the contents of any file readable by the server process …
fickling's UNSAFE_IMPORTS blocklist is missing at least 3 stdlib modules that provide direct arbitrary command execution: uuid, _osx_support, and _aix_support. These modules contain functions that internally call subprocess.Popen() or os.system() with attacker-controlled arguments. A malicious pickle file importing these modules passes both UnsafeImports and NonStandardImports checks.
fickling.always_check_safety() does not hook all pickle entry points. pickle.loads, _pickle.loads, and _pickle.load remain unprotected, enabling malicious payload execution despite global safety mode being enabled.
All 5 of fickling's safety interfaces — is_likely_safe(), check_safety(), CLI –check-safety, always_check_safety(), and the check_safety() context manager — report LIKELY_SAFE / raise no exceptions for pickle files that call dangerous top-level stdlib functions (signal handlers, network servers, network connections, file operations) when the REDUCE opcode is followed by a BUILD opcode. Demonstrated impacts include backdoor network listeners (socketserver.TCPServer), process persistence (signal.signal), outbound data exfiltration (smtplib.SMTP), and file creation on disk …
All 5 of fickling's safety interfaces – is_likely_safe(), check_safety(), CLI –check-safety, always_check_safety(), and the check_safety() context manager – report LIKELY_SAFE / raise no exceptions for pickle files that use the OBJ opcode to call dangerous stdlib functions (signal handlers, network servers, network connections, file operations). The OBJ opcode's implementation in fickling pushes function calls directly onto the interpreter stack without persisting them to the AST via new_variable(). When the result …
Fickling's check_safety() API and –check-safety CLI flag incorrectly rate as LIKELY_SAFE pickle files that open outbound TCP connections at deserialization time using stdlib network-protocol constructors: smtplib.SMTP, imaplib.IMAP4, ftplib.FTP, poplib.POP3, telnetlib.Telnet, and nntplib.NNTP. The bypass exploits two independent root causes described below.
Both ctypes and pydoc modules arent explictly blocked. Even other existing pickle scanning tools (like picklescan) do not block pydoc.locate. Chaining these two together can achieve RCE while the scanner still reports the file as LIKELY_SAFE
Fickling works by Pickle bytecode –> AST –> Security analysis However while going from bytecode to AST, some import nodes are removed which blinds the security analysis fickling/fickling/fickle.py def run(self, interpreter: Interpreter): module, attr = self.module, self.attr if module in ("builtin", "builtins", "builtins"):
The unsafe_imports() method in Fickling's static analyzer fails to flag several high-risk Python modules that can be used for arbitrary code execution. Malicious pickles importing these modules will not be detected as unsafe, allowing attackers to bypass Fickling's primary static safety checks.
Fickling versions up to and including 0.1.6 do not treat Python’s runpy module as unsafe. Because of this, a malicious pickle that uses runpy.run_path() or runpy.run_module() is classified as SUSPICIOUS instead of OVERTLY_MALICIOUS. If a user relies on Fickling’s output to decide whether a pickle is safe to deserialize, this misclassification can lead them to execute attacker-controlled code on their system. This affects any workflow or product that uses Fickling …
Fickling versions up to and including 0.1.6 do not treat Python's cProfile module as unsafe. Because of this, a malicious pickle that uses cProfile.run() is classified as SUSPICIOUS instead of OVERTLY_MALICIOUS. If a user relies on Fickling's output to decide whether a pickle is safe to deserialize, this misclassification can lead them to execute attacker-controlled code on their system. This affects any workflow or product that uses Fickling as a …