CVE-2026-16760: fickling: safe-import trust bypass allows pickle RCE

HIGH
Published October 30, 2026
CISO Take

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.

Sources:NVDATLASbombadil.systemsGitHub (trailofbits/fickling)PyPI

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?

Craft payload
Attacker builds a pickle that calls dataclasses._create_fn, mailcap.findmatch or readline history functions, none of which fickling blocks.
AML.T0018.002
Delivery
The malicious file is distributed as a model or data artifact through a hub, repository or shared drive.
AML.T0010.003
Scanner bypass
fickling.check_safety() trusts the callables by module origin and returns LIKELY_SAFE with zero findings.
AML.T0107
Execution and impact
fickling.load() calls pickle.loads(), running attacker code or writing files with the victim process privileges.
AML.T0011.000

How severe is it?

CVSS 3.1
8.8 / 10
EPSS
0.5%
chance of exploitation in 30 days
Higher than 39% of all CVEs
Exploitation Status
No known exploitation
Sophistication
Moderate

What is the attack surface?

AVACPRUISCIA
AVNetwork
ACLow
PRNone
UIRequired
SUnchanged
CHigh
IHigh
AHigh

What should I do?

6 steps
  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.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

EU AI Act
Art. 15-Accuracy, robustness and cybersecurity
ISO 42001
A.10.3-SuppliersA.7.4-Quality of data for AI systems
NIST AI RMF
MANAGE 3.1-Third-party AI resources risks are monitored and managedMAP 4.1-Risks of third-party software and data are mapped
OWASP LLM Top 10
LLM03-Supply Chain

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

model loading and ingestion pipelinesmodel registries and hubs with pickle scanningtraining pipelinesMLOps CI/CD gatesnotebook-based data science environments

MITRE ATLAS Techniques

AML.T0010.003Model
AML.T0011.000Unsafe AI Artifacts
AML.T0018.002Embed Malware
AML.T0058Publish Poisoned Models
AML.T0074Masquerading
AML.T0107Exploitation for Defense Evasion

Compliance Controls Affected

EU AI Act: Art. 15
ISO 42001: A.10.3, A.7.4
NIST AI RMF: MANAGE 3.1, MAP 4.1
OWASP LLM Top 10: LLM03

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:H

Timeline

Published
October 30, 2026
Last Modified
October 30, 2026
First Seen
October 30, 2026

Related Vulnerabilities