Skip to content

Response, New York. Noah Park: Check Point Patches Actively Exploited Management Server Path Traversal. Detection, Dallas. Ava Okello: Report Finds Nearly Half of Deployed Detections Need Attention Before SOCs Can Trust Them.

SOCtember

Always First. Fast SOC News.

Sysdig illustration of a glass pickle jar with red and orange warning symbols on the pickles, set against a dark grid with red target markers.
Illustration: Sysdig, "In a pickle: Why every pickle defense in machine learning is bypassed the same way," Oct. 27, 2026 (fair use).

Detection

Sysdig Says Every Public Pickle Bypass Beat Machine Learning Model Defenses the Same Way, and Its Runtime Test Shows Why Command-Line Detection Rules Miss the Malicious Load

Sysdig's threat research team traced six documented bypasses of PyTorch, Keras and picklescan protections to one gap: the tool checking a model file and the library loading it read the bytes differently. In its own test, runtime rules caught the consequences of malicious model loads within two seconds, but no rule ever saw the load itself.

Ava Okello, DetectionLondon6 min read

LONDON - Machine learning teams that rely on a scanner or a "safe" loader flag to keep malicious model files out of production are trusting a control that has been beaten the same way six times, according to research published Oct. 27 by Sysdig's Threat Research Team. When the team then loaded hostile model files on monitored hosts, runtime rules flagged what the code did within two seconds, but no rule ever observed the malicious load itself.

The report, by Sysdig senior threat research engineer Lydia Graslie, starts from a point Python's own documentation makes plainly: a pickle file is not data but a short program for a stack-based virtual machine built into CPython, and loading it runs that program. PyTorch's .pt, .pth and .bin files, scikit-learn's joblib files and some NumPy and Keras formats all rely on that mechanism or one like it.

Sysdig listing of a complete pickle protocol 0 payload: a GLOBAL opcode pushes os.system, MARK and TUPLE build the argument "id", REDUCE calls it, and STOP ends the program.
Screenshot: Sysdig Threat Research Team, Oct. 27, 2026 (fair use).Five instructions are enough to make a pickle call os.system on load.

A supply chain that is mostly pickle

Sysdig cites a survey of 705,991 models on a Hugging Face mirror in which PyTorch .pt, .pth and .bin files accounted for 335,893 models, or 51.0%, and explicit pickle variants such as .pkl, .joblib and .dill added 26,696, or 4.1%. The same survey found 91 malicious models, 15 of which used Keras Lambda layers. By Sysdig's reading, more than half of the models in that sample execute code the moment they are loaded.

Formats that store only named arrays of numbers are different. Sysdig classes safetensors as structurally safe because it holds tensors and a JSON header with no way to express a call, and lists GGUF and ONNX as having no known code execution path, a weaker claim that reflects the current state of research.

One bug, six times

The ecosystem has tried two fixes: restrict the loader to a safe subset of callables, or scan files before they load. Sysdig says both have been bypassed.

PyTorch made weights_only=True the default for torch.load in version 2.6. CVE-2025-32434 showed the flag was not enforced on the _legacy_load path used for older checkpoints in 2.5.1 and earlier. CVE-2026-24747, published in January 2026 with a CVSS score of 8.8, defeats the restricted unpickler's validation with crafted opcodes and affects every version before 2.10.0. Keras made safe_mode the default from 2.13, but CVE-2025-9905 ignores it on the legacy .h5 path, and CVE-2025-9906 lets a crafted .keras archive turn off unsafe-deserialization protection before dropping a Lambda layer.

Scanners fared no better. Sonatype disclosed four picklescan vulnerabilities in 2025, including one where detection keyed on file extension rather than content and two where malformed ZIP structures crashed or blinded the scanner while PyTorch still loaded the file. The nullifAI models that ReversingLabs found on Hugging Face in February 2025 were compressed with 7z, which picklescan did not parse, and were deliberately corrupted after the payload so the code ran before the loader hit an error.

Sysdig table pairing six bypasses with the gap each exploited: PyTorch CVE-2025-32434, Keras CVE-2025-9905 and CVE-2025-9906, picklescan CVE-2025-1889, CVE-2025-1944 and 1945, and nullifAI.
Table: Sysdig Threat Research Team, Oct. 27, 2026 (fair use).In every case the checker and the loader disagreed about what the file was.

"In every case, the thing doing the checking and the thing doing the loading disagreed about what the file was," the report says. The attacker did not defeat the check, Sysdig argues, but found a reading of the file on which the check did not apply.

What runtime rules saw

To measure the layer usually offered as the backstop, the team built five hostile gadget families, each a pickle whose __reduce__ method performs a different post-exploitation action, and ran them against open source Falco 0.44.1 on its default ruleset and against Sysdig's commercial Sysdig Secure product. Both runs fired a positive control first, and the team says it wrote down all five predicted outcomes before running them.

Sysdig results table for five pickle gadget families against OSS Falco defaults and Sysdig Secure, showing sensitive file reads caught in 1.5 to 1.9 seconds and a .pth startup-hook persistence case.
Table: Sysdig Threat Research Team, Oct. 27, 2026 (fair use).Detection results for five malicious pickle gadget families.

Sysdig Secure flagged all five within two seconds. Falco's default ruleset caught four of the five; Sysdig notes that the open source defaults contain 26 rules against 278 in the commercial product, and that the Falco rule Modify Python Startup Hook File, listed against the fifth case, was created after the test. A gadget that spawned a shell was caught in 1.6 seconds, one that read a sensitive file directly in 1.9 seconds and one that never left the Python process in 1.5 seconds, all by the same rule. Whether a gadget forks, the report concludes, does not decide whether it is visible.

The more important finding for detection engineers is what never fired. Rules such as Shell Spawned with Inline Python Command and Base64-encoded Python Script Execution look for malicious Python on the process command line. A pickle load is an ordinary command like python3 load_pickle.py model.pkl, and the gadget lives in the file, so that text never appears at any encoding layer. Runtime sensors caught the file reads, outbound connections and persistence writes that followed, not the deserialization.

What SOC and platform teams should take from it

Sysdig orders its defenses by how they fail. Convert models to safetensors where possible. Pin PyTorch at 2.10.0 or later, refuse legacy Keras .h5 inputs and keep NumPy's allow_pickle off, while treating any code that flips it as a finding. Scan in CI with modelscan or picklescan, but never let a clean scan promote an artifact on its own. Track provenance, load untrusted models in a sandbox with no useful credentials and an explicit egress allowlist, and keep runtime detection as the backstop.

For a SOC, the practical reading is that model-loading hosts need behavior-based coverage on what a Python process touches after it opens a model file: reads of credential and secrets paths, unexpected outbound connections and writes to Python .pth startup files. Detections that depend on seeing malicious code on a command line will not see this class of attack.

Sources:


Ava Okello covers detection engineering, EDR telemetry, and SOC hunting for SOCtember from London.

Related stories

Detection desk