VYPR
High severityOSV Advisory· Published Jan 10, 2026· Updated Jan 13, 2026

Fickling vulnerable to use of ctypes and pydoc gadget chain to bypass detection

CVE-2026-22608

Description

Fickling is a Python pickling decompiler and static analyzer. Prior to version 0.1.7, both ctypes and pydoc modules aren't explicitly 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. This issue has been patched in version 0.1.7.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ficklingPyPI
< 0.1.70.1.7

Affected products

1

Patches

2
d0b00d584afb

Simplify test case for GHSA-5hvc-6wx8-mvv4 so it doesn't import Exception

https://github.com/trailofbits/ficklingThomas ChauchefoinJan 8, 2026via ghsa
1 file changed · +16 19
  • test/test_bypasses.py+16 19 modified
    @@ -191,28 +191,25 @@ def test_missing_ctypes(self):
         def test_missing_pydoc(self):
             pickled = Pickled(
                 [
    -                op.Global("pydoc locate"),
    -                op.String("ctypes.windll.kernel32.WinExec"),
    +                op.Proto.create(5),
    +                op.ShortBinUnicode("pydoc"),
    +                op.Memoize(),
    +                op.ShortBinUnicode("locate"),
    +                op.Memoize(),
    +                op.StackGlobal(),
    +                op.Memoize(),
    +                op.ShortBinUnicode("os.system"),
    +                op.Memoize(),
                     op.TupleOne(),
    +                op.Memoize(),
                     op.Reduce(),
    -                op.Put(0),
    -                op.Pop(),
    -                op.Get(0),
    -                op.ShortBinBytes(b"calc.exe"),
    -                op.BinInt1(1),
    -                op.TupleTwo(),
    -                op.Reduce(),
    -                op.Put(1),
    -                op.Pop(),
    -                op.Global("builtins Exception"),
    -                op.EmptyTuple(),
    +                op.Memoize(),
    +                op.ShortBinUnicode("id"),
    +                op.Memoize(),
    +                op.TupleOne(),
    +                op.Memoize(),
                     op.Reduce(),
    -                op.Put(2),
    -                op.EmptyDict(),
    -                op.String("rce_status"),
    -                op.Get(1),
    -                op.SetItem(),
    -                op.Build(),
    +                op.Memoize(),
                     op.Stop(),
                 ]
             )
    
b793563e60a5

Add pydoc and ctypes to unsafe imports

https://github.com/trailofbits/ficklingThomas ChauchefoinJan 7, 2026via ghsa
2 files changed · +84 0
  • fickling/fickle.py+2 0 modified
    @@ -880,6 +880,8 @@ def unsafe_imports(self) -> Iterator[ast.Import | ast.ImportFrom]:
                     "types",
                     "runpy",
                     "cProfile",
    +                "ctypes",
    +                "pydoc",
                 ):
                     yield node
                 elif "eval" in (n.name for n in node.names):
    
  • test/test_bypasses.py+82 0 modified
    @@ -139,3 +139,85 @@ def test_missing_cprofile(self):
                 res.detailed_results()["AnalysisResult"].get("UnsafeImports"),
                 "from cProfile import run",
             )
    +
    +    # https://github.com/trailofbits/fickling/security/advisories/GHSA-q5qq-mvfm-j35x
    +    # https://github.com/trailofbits/fickling/security/advisories/GHSA-5hvc-6wx8-mvv4
    +    def test_missing_ctypes(self):
    +        pickled = Pickled(
    +            [
    +                op.Proto.create(5),
    +                op.ShortBinUnicode("builtins"),
    +                op.Memoize(),
    +                op.ShortBinUnicode("getattr"),
    +                op.Memoize(),
    +                op.StackGlobal(),
    +                op.Memoize(),
    +                op.ShortBinUnicode("ctypes"),
    +                op.Memoize(),
    +                op.ShortBinUnicode("CDLL"),
    +                op.Memoize(),
    +                op.StackGlobal(),
    +                op.Memoize(),
    +                op.ShortBinUnicode("libc.dylib"),
    +                op.Memoize(),
    +                op.TupleOne(),
    +                op.Memoize(),
    +                op.Reduce(),
    +                op.Memoize(),
    +                op.ShortBinUnicode("system"),
    +                op.Memoize(),
    +                op.TupleTwo(),
    +                op.Memoize(),
    +                op.Reduce(),
    +                op.Memoize(),
    +                op.ShortBinBytes(b"id"),
    +                op.Memoize(),
    +                op.TupleOne(),
    +                op.Memoize(),
    +                op.Reduce(),
    +                op.Memoize(),
    +                op.Stop(),
    +            ]
    +        )
    +        res = check_safety(pickled)
    +        self.assertGreater(res.severity, Severity.LIKELY_SAFE)
    +        self.assertEqual(
    +            res.detailed_results()["AnalysisResult"].get("UnsafeImports"),
    +            "from ctypes import CDLL",
    +        )
    +
    +    # https://github.com/trailofbits/fickling/security/advisories/GHSA-5hvc-6wx8-mvv4
    +    def test_missing_pydoc(self):
    +        pickled = Pickled(
    +            [
    +                op.Global("pydoc locate"),
    +                op.String("ctypes.windll.kernel32.WinExec"),
    +                op.TupleOne(),
    +                op.Reduce(),
    +                op.Put(0),
    +                op.Pop(),
    +                op.Get(0),
    +                op.ShortBinBytes(b"calc.exe"),
    +                op.BinInt1(1),
    +                op.TupleTwo(),
    +                op.Reduce(),
    +                op.Put(1),
    +                op.Pop(),
    +                op.Global("builtins Exception"),
    +                op.EmptyTuple(),
    +                op.Reduce(),
    +                op.Put(2),
    +                op.EmptyDict(),
    +                op.String("rce_status"),
    +                op.Get(1),
    +                op.SetItem(),
    +                op.Build(),
    +                op.Stop(),
    +            ]
    +        )
    +        res = check_safety(pickled)
    +        self.assertGreater(res.severity, Severity.LIKELY_SAFE)
    +        self.assertEqual(
    +            res.detailed_results()["AnalysisResult"].get("UnsafeImports"),
    +            "from pydoc import locate",
    +        )
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.