CVE-2026-14535: CWE-693 Protection Mechanism Failure in trailofbits fickling
In Trail of Bits fickling versions up to and including 0.1.11, the UnsafeImportsML analysis pass unconditionally calls AnalysisContext.shorten_code(node) on every import node it inspects, regardless of whether the import is flagged as unsafe. This call registers the shortened code representation in the shared AnalysisContext.reported_shortened_code set. When the MLAllowlist analysis pass subsequently runs, it calls the same shorten_code() method, receives already_reported=True for every import, and executes a continue statement that skips its allowlist check entirely. This renders MLAllowlist dead code for all imports — it never evaluates whether an import is in the ML allowlist or not. The MLAllowlist pass was designed to catch imports of modules outside the known-safe ML ecosystem (torch, numpy, transformers, etc.) that slip past the UnsafeImports denylist. With MLAllowlist inoperative, any standard library module not in the UNSAFE_IMPORTS denylist can be invoked via pickle deserialization while fickling's check_safety() returns LIKELY_SAFE. The fickling.load() API chains check_safety() into pickle.loads() as an explicit security gate, meaning a LIKELY_SAFE verdict causes the payload to be deserialized and executed. The root cause is shared mutable state between independently-correct analysis passes — UnsafeImportsML works as designed in isolation, MLAllowlist works as designed in isolation, but the shared reported_shortened_code set causes UnsafeImportsML to poison MLAllowlist's deduplication logic.
AI Analysis
Technical Summary
In fickling versions <=0.1.11, the UnsafeImportsML analysis pass calls AnalysisContext.shorten_code(node) on every import node, registering the shortened code in a shared set. When the MLAllowlist pass runs, it calls shorten_code() and finds all imports already reported, causing it to skip its allowlist checks entirely. This shared mutable state between the two analysis passes causes MLAllowlist to become dead code, allowing imports not flagged as unsafe to be used during pickle deserialization. Since fickling.load() uses check_safety() as a gate before deserialization, and check_safety() returns LIKELY_SAFE for these imports, malicious payloads can be deserialized and executed. The root cause is the interference of shared state between independently correct analysis passes.
Potential Impact
This vulnerability allows attackers to bypass the MLAllowlist security check, enabling the deserialization and execution of potentially unsafe modules via pickle. This can lead to arbitrary code execution with the privileges of the process running fickling.load(). The CVSS score of 8.8 reflects high impact on confidentiality, integrity, and availability.
Mitigation Recommendations
Patch status is not yet confirmed — check the vendor advisory for current remediation guidance. Until a fix is available, users should avoid using affected versions (<=0.1.11) of fickling or avoid relying on fickling.load() for untrusted pickle data. Monitoring vendor communications for an official fix or temporary mitigation is recommended.
CVE-2026-14535: CWE-693 Protection Mechanism Failure in trailofbits fickling
Description
In Trail of Bits fickling versions up to and including 0.1.11, the UnsafeImportsML analysis pass unconditionally calls AnalysisContext.shorten_code(node) on every import node it inspects, regardless of whether the import is flagged as unsafe. This call registers the shortened code representation in the shared AnalysisContext.reported_shortened_code set. When the MLAllowlist analysis pass subsequently runs, it calls the same shorten_code() method, receives already_reported=True for every import, and executes a continue statement that skips its allowlist check entirely. This renders MLAllowlist dead code for all imports — it never evaluates whether an import is in the ML allowlist or not. The MLAllowlist pass was designed to catch imports of modules outside the known-safe ML ecosystem (torch, numpy, transformers, etc.) that slip past the UnsafeImports denylist. With MLAllowlist inoperative, any standard library module not in the UNSAFE_IMPORTS denylist can be invoked via pickle deserialization while fickling's check_safety() returns LIKELY_SAFE. The fickling.load() API chains check_safety() into pickle.loads() as an explicit security gate, meaning a LIKELY_SAFE verdict causes the payload to be deserialized and executed. The root cause is shared mutable state between independently-correct analysis passes — UnsafeImportsML works as designed in isolation, MLAllowlist works as designed in isolation, but the shared reported_shortened_code set causes UnsafeImportsML to poison MLAllowlist's deduplication logic.
CVSS v3.1
Score 8.8high
Affected software
Run on your own infrastructure? Check whether these packages are installed with threat-finder — our free open-source scanner.
Weaknesses
AI-Powered Analysis
Machine-generated threat intelligence
Technical Analysis
In fickling versions <=0.1.11, the UnsafeImportsML analysis pass calls AnalysisContext.shorten_code(node) on every import node, registering the shortened code in a shared set. When the MLAllowlist pass runs, it calls shorten_code() and finds all imports already reported, causing it to skip its allowlist checks entirely. This shared mutable state between the two analysis passes causes MLAllowlist to become dead code, allowing imports not flagged as unsafe to be used during pickle deserialization. Since fickling.load() uses check_safety() as a gate before deserialization, and check_safety() returns LIKELY_SAFE for these imports, malicious payloads can be deserialized and executed. The root cause is the interference of shared state between independently correct analysis passes.
Potential Impact
This vulnerability allows attackers to bypass the MLAllowlist security check, enabling the deserialization and execution of potentially unsafe modules via pickle. This can lead to arbitrary code execution with the privileges of the process running fickling.load(). The CVSS score of 8.8 reflects high impact on confidentiality, integrity, and availability.
Mitigation Recommendations
Patch status is not yet confirmed — check the vendor advisory for current remediation guidance. Until a fix is available, users should avoid using affected versions (<=0.1.11) of fickling or avoid relying on fickling.load() for untrusted pickle data. Monitoring vendor communications for an official fix or temporary mitigation is recommended.
Technical Details
- Data Version
- 5.2
- Assigner Short Name
- BombadilSystems
- Date Reserved
- 2026-07-03T00:02:55.918Z
- Cvss Version
- 3.1
- State
- PUBLISHED
- Remediation Level
- null
Threat ID: 6a49100627e9c797194461f2
Added to database: 07/04/2026, 13:52:06 UTC
Last enriched: 07/12/2026, 08:55:49 UTC
Last updated: 08/18/2026, 22:49:25 UTC
Views: 119
Community Reviews
0 reviewsCrowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.
Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.
Actions
Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.
Need more coverage?
Upgrade to Pro Console for AI refresh and higher limits.
For incident response and remediation, OffSeq services can help resolve threats faster.
Latest Threats
Check if your credentials are on the dark web
Instant breach scanning across billions of leaked records. Free tier available.