CVE-2026-16760: fickling: safe-import trust bypass allows pickle RCE
HIGHFickling, the Trail of Bits tool many teams use as a security gate for untrusted pickle files, can be tricked into reporting malicious pickles as LIKELY_SAFE with zero findings. It trusts any callable from a non-denylisted standard library module, so payloads built on dataclasses._create_fn, mailcap.findmatch or readline history writing get arbitrary code execution or file write when fickling.load() passes them to pickle.loads(). This matters because the control meant to stop model-file attacks becomes a false assurance, and teams that rely on it for ingesting third-party models or artifacts are exposed. There is no EPSS score, no KEV listing and no public exploit yet, but the advisory describes the primitives in detail, and the attack needs only low complexity plus a user opening a crafted file. Released versions through 0.1.12 are affected; the fix is only on the master branch (commit d011709) and is not yet released, and the related CVE-2026-118938 remains exploitable. Until a release ships, do not treat a fickling verdict as sufficient. Load untrusted pickles only in sandboxed environments, or prefer safetensors or other non-executable formats.
What is the risk?
High (CVSS 8.8). Exploitation is low complexity with no privileges, but a user or pipeline must load the crafted file. Impact on the victim process is full: code execution or arbitrary file write. The main risk is the false sense of security. Teams may skip sandboxing because a scanner said LIKELY_SAFE. The fix on master is a denylist addition covering only the three demonstrated modules, so the root cause (inferring safety from module origin) persists and new bypasses are likely. Exploit data is limited: EPSS is unavailable, there is no KEV entry and no public exploit, though the advisory documents the primitives. Package risk score and dependent counts are unknown.
How does the attack unfold?
How severe is it?
What is the attack surface?
What should I do?
6 stepsUpgrade fickling as soon as a release containing commit d011709 is published, and track CVE-2026-118938 for a separate fix. Until then, versions through 0.1.12 are vulnerable.
Do not rely on a LIKELY_SAFE verdict as the only control: load untrusted pickles only in isolated sandboxes (containers or VMs with no credentials and no network).
Prefer safetensors, ONNX or other non-executable formats for model exchange.
Where fickling is a gate, add a second scanner and run Python 3.13 or later to remove the _create_fn and mailcap primitives, noting that the readline write primitive remains.
Detection: monitor for unexpected child processes, exec calls and writes to shell profiles or config paths from model-loading processes. Audit past files that fickling cleared, particularly those from external sources.
Reject pickles referencing dataclasses, mailcap or readline imports.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-16760?
Fickling, the Trail of Bits tool many teams use as a security gate for untrusted pickle files, can be tricked into reporting malicious pickles as LIKELY_SAFE with zero findings. It trusts any callable from a non-denylisted standard library module, so payloads built on dataclasses._create_fn, mailcap.findmatch or readline history writing get arbitrary code execution or file write when fickling.load() passes them to pickle.loads(). This matters because the control meant to stop model-file attacks becomes a false assurance, and teams that rely on it for ingesting third-party models or artifacts are exposed. There is no EPSS score, no KEV listing and no public exploit yet, but the advisory describes the primitives in detail, and the attack needs only low complexity plus a user opening a crafted file. Released versions through 0.1.12 are affected; the fix is only on the master branch (commit d011709) and is not yet released, and the related CVE-2026-118938 remains exploitable. Until a release ships, do not treat a fickling verdict as sufficient. Load untrusted pickles only in sandboxed environments, or prefer safetensors or other non-executable formats.
Is CVE-2026-16760 actively exploited?
No confirmed active exploitation of CVE-2026-16760 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-16760?
1. Upgrade fickling as soon as a release containing commit d011709 is published, and track CVE-2026-118938 for a separate fix. Until then, versions through 0.1.12 are vulnerable. 2. Do not rely on a LIKELY_SAFE verdict as the only control: load untrusted pickles only in isolated sandboxes (containers or VMs with no credentials and no network). 3. Prefer safetensors, ONNX or other non-executable formats for model exchange. 4. Where fickling is a gate, add a second scanner and run Python 3.13 or later to remove the _create_fn and mailcap primitives, noting that the readline write primitive remains. 5. Detection: monitor for unexpected child processes, exec calls and writes to shell profiles or config paths from model-loading processes. Audit past files that fickling cleared, particularly those from external sources. 6. Reject pickles referencing dataclasses, mailcap or readline imports.
What systems are affected by CVE-2026-16760?
This vulnerability affects the following AI/ML architecture patterns: model loading and ingestion pipelines, model registries and hubs with pickle scanning, training pipelines, MLOps CI/CD gates, notebook-based data science environments.
What is the CVSS score for CVE-2026-16760?
CVE-2026-16760 has a CVSS v3.1 base score of 8.8 (HIGH). The EPSS exploitation probability is 0.46%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0010.003ModelAML.T0011.000Unsafe AI ArtifactsAML.T0018.002Embed MalwareAML.T0058Publish Poisoned ModelsAML.T0074MasqueradingAML.T0107Exploitation for Defense EvasionCompliance Controls Affected
What are the technical details?
Original Advisory
In Trail of Bits fickling through 0.1.12, the _process_import() method in fickle.py adds an imported name to the likely_safe_imports set whenever the source module is present in sys.stdlib_module_names and the name is absent from the UNSAFE_IMPORTS denylist, without inspecting what the name resolves to or how it behaves. The OvertlyBadEvals analysis pass in analysis.py then unconditionally skips any call whose function name appears in likely_safe_imports, including calls that would otherwise be flagged as overtly dangerous. As a result, any callable reachable through a non-blocked standard library module inherits module-level trust regardless of its own behavior, and check_safety() returns LIKELY_SAFE with zero findings for pickle payloads that reach code execution or file write through such callables. Demonstrated primitives: dataclasses._create_fn, which passes an attacker-controlled function body to exec() and yields arbitrary code execution on Python 3.7 through 3.12 (the internal _create_fn function was removed in Python 3.13); mailcap.findmatch, which internally calls os.system() on a test command taken from an attacker-controlled caps dictionary, yielding arbitrary code execution on Python versions through 3.12 (the mailcap module was removed in Python 3.13); and readline.add_history() followed by readline.write_history_file(), which writes attacker-controlled content to an arbitrary filesystem path (POSIX platforms, where the readline module is available). fickling.load() chains check_safety() into pickle.loads() as an explicit security gate, so a LIKELY_SAFE verdict causes the payload to be deserialized and executed with the privileges of the victim process. The root cause is the inference of callable safety from module origin; it is independent of, and separately fixable from, the dotted __qualname__ resolution weakness tracked as CVE-2026-118938, which this advisory does not address. As of 2026-10-30 the three demonstrated modules were added to UNSAFE_IMPORTS on the vendor master branch (commit d011709) pending release; released versions through 0.1.12 remain affected, and the module-origin trust root cause persists, as demonstrated by the related CVE-2026-118938 remaining exploitable on that same build.
Exploitation Scenario
An attacker publishes a model checkpoint on a public hub or sends it to a data science team as a shared artifact. The pickle contains a crafted call to dataclasses._create_fn with an attacker-controlled function body, or mailcap.findmatch with a malicious test command. The team's ingestion pipeline runs fickling.load(), which returns LIKELY_SAFE with no findings and then deserializes the file. The payload runs inside the training or inference host, steals cloud credentials and API keys, and installs persistence. Alternatively, the readline primitive overwrites ~/.bashrc or an authorized_keys file to gain a later foothold.
Weaknesses (CWE)
CWE-502 — Deserialization of Untrusted Data: The product deserializes untrusted data without sufficiently ensuring that the resulting data will be valid.
- [Architecture and Design, Implementation] If available, use the signing/sealing features of the programming language to assure that deserialized data has not been tainted. For example, a hash-based message authentication code (HMAC) could be used to ensure that data has not been modified.
- [Implementation] When deserializing data, populate a new object rather than just deserializing. The result is that the data flows through safe input validation and that the functions are safe.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:HReferences
Timeline
Related Vulnerabilities
CVE-2025-5952810.0Flowise: Unauthenticated RCE via MCP config injection
Same attack type: Supply ChainCVE-2024-291210.0BentoML: RCE via insecure deserialization (CVSS 10)
Same attack type: Supply ChainCVE-2023-376510.0MLflow: path traversal allows arbitrary file read
Same attack type: Supply ChainCVE-2025-512010.0smolagents: sandbox escape enables unauthenticated RCE
Same attack type: Supply ChainCVE-2026-2185810.0n8n: Input Validation flaw enables exploitation
Same attack type: Code Execution