manja316's picture
Upload folder using huggingface_hub
11a7366 verified
# modelscan Bypass PoC: distutils.spawn.spawn()
## Vulnerability
modelscan 0.7.6 fails to detect malicious pickle files that use `distutils.spawn.spawn()` for command execution. The `distutils.spawn` module is not included in modelscan's `unsafe_globals` blocklist.
## Attack Chain
Minimal single-REDUCE chain:
1. `STACK_GLOBAL "distutils.spawn" "spawn"` — loads the spawn function
2. Build argument list `["sh", "-c", "arbitrary_command"]`
3. `REDUCE` — calls `spawn(["sh", "-c", "arbitrary_command"])`
## Impact
- **Full RCE** via `pickle.load()` or `torch.load()`
- Bypasses modelscan 0.7.6 completely — reports "No issues found"
- Extremely simple chain — single function call, no chaining needed
- `distutils.spawn.spawn()` internally calls `os.spawnv()` but this is invisible to modelscan's static opcode analysis
## Reproduction
```bash
python create_poc.py
modelscan scan -p pytorch_model.bin
# Output: "No issues found"
python -c "import pickle; pickle.loads(open('pytorch_model.bin','rb').read())"
# Creates /tmp/distutils_bypass_proof
```
## Root Cause
modelscan only checks top-level module references in pickle GLOBAL/STACK_GLOBAL opcodes against its blocklist. `distutils.spawn` is not listed. The internal delegation to `os.spawnv()` happens at Python runtime, not in pickle bytecode.
## Fix Recommendation
Add `"distutils.spawn": "*"` to `unsafe_globals.CRITICAL` in `modelscan/settings.py`.