{"id":"CVE-2026-14535","url":"https://www.cyber-defence.io/tools/cve/CVE-2026-14535","generatedAt":"2026-10-28T04:31:03.565Z","title":"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.","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.","published":"2026-07-04T14:16:29.000Z","lastModified":"2026-10-25T15:10:00.000Z","status":"Analyzed","sourceIdentifier":"aa17e1a1-c329-4d6e-a1ed-8d0188aea082","cvss":{"version":"3.1","score":9.8,"severity":"CRITICAL","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"},"cwe":["CWE-693"],"affected":["trailofbits/fickling"],"epss":{"score":0.00564,"percentile":0.46713,"date":"2026-10-27","history":[]},"kev":{"listed":false},"exploits":{"count":0,"verified":false,"firstPublished":null,"source":"Exploit-DB (https://gitlab.com/exploit-database/exploitdb)","entries":[]},"verdict":{"level":"high","text":"High impact if exploited, but EPSS currently rates exploitation as unlikely (0.56%). Schedule it in the normal patch cycle and watch for a rise in EPSS or a public exploit."},"changes":[],"references":[{"url":"https://github.com/trailofbits/fickling/commit/41ce7cb01edd97072994039574a2301ebb3f463d","tags":["Patch"],"source":"aa17e1a1-c329-4d6e-a1ed-8d0188aea082"},{"url":"https://github.com/trailofbits/fickling/pull/278","tags":["Issue Tracking","Patch"],"source":"aa17e1a1-c329-4d6e-a1ed-8d0188aea082"},{"url":"https://github.com/trailofbits/fickling/releases/tag/v0.1.12","tags":["Release Notes"],"source":"aa17e1a1-c329-4d6e-a1ed-8d0188aea082"},{"url":"https://github.com/trailofbits/fickling/security/advisories/GHSA-cffv-grgg-g429","tags":["Exploit","Third Party Advisory"],"source":"aa17e1a1-c329-4d6e-a1ed-8d0188aea082"},{"url":"https://github.com/trailofbits/fickling/security/advisories/GHSA-cffv-grgg-g429","tags":["Exploit","Third Party Advisory"],"source":"134c704f-9b21-4f2e-91b3-4a467353bcc0"}],"sources":{"nvd":"https://nvd.nist.gov/vuln/detail/CVE-2026-14535","epss":"https://www.first.org/epss/","kev":"https://www.cisa.gov/known-exploited-vulnerabilities-catalog","exploitdb":"https://www.exploit-db.com/"},"licence":"CC BY 4.0 — link back to the CVE Explorer if you publish the results; upstream data remains subject to its own terms."}