Repository: promptfoo/promptfoo
Issue: modelaudit scan hangs indefinitely on malicious pickle model (ykilcher/totally-harmless-model)
Root cause: Algorithmic Error

When scanning the HuggingFace model ykilcher/totally-harmless-model, the scan detects multiple CRITICAL pickle-based malicious patterns — but the process never completes. The CLI gets stuck after emitting CRITICAL findings and never writes the JSON output or returns control to the shell.

important
This issue does **NOT** happen on normal, non-malicious models (e.g., SafeTensors models, clean PyTorch models).
Only this malicious pickle payload causes the hang.

This happens even when using:

`modelaudit scan https://huggingface.co/ykilcher/totally-harmless-model --format json --output results_3.json --verbose`

The scanner logs many valid CRITICAL findings, but then appears to hang during or after the pickle opcode analysis phase.

output

> Progress tracking disabled during scanner initialization
> 2025-11-20 17:11:01,758 - modelaudit.interrupt - DEBUG - Interrupt handlers installed
> 2025-11-20 17:11:02,103 - modelaudit.core - DEBUG - Skipping non-model file: /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/.cache/huggingface/.gitignore
> 2025-11-20 17:11:02,103 - modelaudit.core - DEBUG - Skipping non-model file: /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/.cache/huggingface/download/README.md.lock
> 2025-11-20 17:11:02,104 - modelaudit.core - DEBUG - Skipping non-model file: /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/.cache/huggingface/download/config.json.lock
> 2025-11-20 17:11:02,104 - modelaudit.core - DEBUG - Skipping non-model file: /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/.cache/huggingface/download/pytorch_model.bin.lock
> 2025-11-20 17:11:02,275 - modelaudit.utils.helpers.cache_decorator - DEBUG - File /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/README.md not suitable for caching, calling function directly
> 2025-11-20 17:11:02,275 - modelaudit.core - DEBUG - Processing: /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/README.md
> 2025-11-20 17:11:02,276 - modelaudit.scanners - DEBUG - Loaded scanner: metadata
> 2025-11-20 17:11:02,276 - modelaudit.core - DEBUG - Using base scanner for /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/README.md
> 2025-11-20 17:11:02,276 - modelaudit.utils.helpers.cache_decorator - DEBUG - File /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/README.md not suitable for caching, calling function directly
> 2025-11-20 17:11:02,278 - modelaudit.utils.helpers.cache_decorator - DEBUG - File /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/config.json not suitable for caching, calling function directly
> 2025-11-20 17:11:02,279 - modelaudit.core - DEBUG - Processing: /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/config.json
> 2025-11-20 17:11:02,279 - modelaudit.scanners - DEBUG - Loaded scanner: xgboost
> 2025-11-20 17:11:02,279 - modelaudit.scanners - DEBUG - Loaded scanner: manifest
> 2025-11-20 17:11:02,279 - modelaudit.core - DEBUG - Using manifest scanner for /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/config.json
> 2025-11-20 17:11:02,279 - modelaudit.utils.helpers.cache_decorator - DEBUG - File /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/config.json not suitable for caching, calling function directly
> 2025-11-20 17:11:02,279 - modelaudit.scanners - DEBUG - Check passed: Path Exists - Path exists
> 2025-11-20 17:11:02,280 - modelaudit.scanners - DEBUG - Check passed: Path Readable - Path is readable
> 2025-11-20 17:11:02,280 - modelaudit.scanners - DEBUG - Check passed: File Type Validation - File type validation passed
> 2025-11-20 17:11:02,280 - modelaudit.utils.helpers.cache_decorator - DEBUG - File /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin not suitable for caching, calling function directly
> 2025-11-20 17:11:02,280 - modelaudit.core - DEBUG - Processing: /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin
> 2025-11-20 17:11:02,318 - modelaudit.scanners - DEBUG - Loaded scanner: pickle
> 2025-11-20 17:11:02,319 - modelaudit.scanners - DEBUG - Loaded scanner: pytorch_zip
> 2025-11-20 17:11:02,319 - modelaudit.core - DEBUG - Using pytorch_zip scanner for /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin
> 2025-11-20 17:11:02,319 - modelaudit.utils.helpers.cache_decorator - DEBUG - File /home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin not suitable for caching, calling function directly
> 2025-11-20 17:11:02,319 - modelaudit.scanners - DEBUG - Check passed: Path Exists - Path exists
> 2025-11-20 17:11:02,319 - modelaudit.scanners - DEBUG - Check passed: Path Readable - Path is readable
> 2025-11-20 17:11:02,319 - modelaudit.scanners - DEBUG - Check passed: File Type Validation - File type validation passed
> 2025-11-20 17:11:02,999 - modelaudit.scanners - DEBUG - Check passed: File Integrity Hash - File integrity hashes calculated
> 2025-11-20 17:11:03,000 - modelaudit.scanners - DEBUG - Check passed: PyTorch ZIP Format Validation - Valid ZIP format detected
> 2025-11-20 17:11:03,003 - modelaudit.scanners - DEBUG - Check passed: Path Traversal Protection - All archive entries have safe paths
> 2025-11-20 17:11:03,701 - modelaudit.scanners - CRITICAL - [CRITICAL] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl): Detected code_eval pattern: 'exec('
> 2025-11-20 17:11:03,701 - modelaudit.scanners - CRITICAL - [CRITICAL] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl): Detected network_ops pattern: 'webbrowser.open', 'webbrowser'
> 2025-11-20 17:11:03,701 - modelaudit.scanners - WARNING - [WARNING] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl): Detected file_operations pattern: 'open('
> 2025-11-20 17:11:03,701 - modelaudit.scanners - WARNING - [WARNING] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl): Legacy dangerous pattern detected: import sys
> 2025-11-20 17:11:03,701 - modelaudit.scanners - WARNING - [WARNING] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl): Legacy dangerous pattern detected: exec(
> 2025-11-20 17:11:03,702 - modelaudit.scanners - WARNING - [WARNING] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl): Legacy dangerous pattern detected: open(
> 2025-11-20 17:11:03,713 - modelaudit.scanners - DEBUG - Check passed: Embedded Secrets Detection - No embedded secrets detected      
> 2025-11-20 17:11:03,718 - modelaudit.scanners - DEBUG - Check passed: JIT/Script Code Execution Summary - No JIT/Script code execution risks detected
> 2025-11-20 17:11:03,718 - modelaudit.scanners - INFO - [INFO] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl): Found 2 network communication patterns (Domain name detected: ykilcher.com, https://ykilcher.com/pickle, ykilcher.com) across file
> 2025-11-20 17:11:03,718 - modelaudit.scanners - DEBUG - Check passed: Pickle Protocol Version Check - Valid pickle protocol version 2
> 2025-11-20 17:11:03,718 - modelaudit.analysis.opcode_sequence_analyzer - DEBUG - Stack simulation error for GLOBAL: too many values to unpack (expected 2)
> 2025-11-20 17:11:03,718 - modelaudit.analysis.opcode_sequence_analyzer - DEBUG - Stack simulation error for GLOBAL: too many values to unpack (expected 2)
> 2025-11-20 17:11:03,718 - modelaudit.analysis.opcode_sequence_analyzer - DEBUG - Stack simulation error for GLOBAL: too many values to unpack (expected 2)
> 2025-11-20 17:11:03,718 - modelaudit.analysis.opcode_sequence_analyzer - DEBUG - Stack simulation error for GLOBAL: too many values to unpack (expected 2)
> 2025-11-20 17:11:03,725 - modelaudit.scanners - DEBUG - Check passed: Opcode Count Check - Opcode count (3093) is within limits      
> 2025-11-20 17:11:03,725 - modelaudit.scanners - DEBUG - Check passed: Stack Depth Validation - Maximum stack depth (401) is within safe limits
> 2025-11-20 17:11:03,725 - modelaudit.scanners - DEBUG - Allowlisted safe global from potentially dangerous module: collections.OrderedDict
> 2025-11-20 17:11:03,725 - modelaudit.scanners - DEBUG - Allowlisted safe global from potentially dangerous module: torch.FloatStorage
> 2025-11-20 17:11:03,725 - modelaudit.scanners - WARNING - Always-dangerous function detected: __builtin__.eval (flagged regardless of ML context confidence=0.32)
> 2025-11-20 17:11:03,725 - modelaudit.scanners - CRITICAL - [CRITICAL] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl): Suspicious reference __builtin__.eval
> 2025-11-20 17:11:03,725 - modelaudit.scanners - DEBUG - Allowlisted safe global from potentially dangerous module: torch._utils._rebuild_tensor_v2
> 2025-11-20 17:11:03,725 - modelaudit.scanners - WARNING - Always-dangerous function detected: __builtin__.eval (flagged regardless of ML context confidence=0.32)
> 2025-11-20 17:11:03,725 - modelaudit.scanners - CRITICAL - [CRITICAL] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl (pos 2)): Suspicious reference __builtin__.eval
> 2025-11-20 17:11:03,725 - modelaudit.scanners - WARNING - Always-dangerous function detected: __builtin__.eval (flagged regardless of ML context confidence=0.32)
> 2025-11-20 17:11:03,725 - modelaudit.scanners - CRITICAL - [CRITICAL] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl (pos 160)): Found REDUCE opcode with non-allowlisted global: __builtin__.eval. This may indicate CVE-2025-32434 exploitation (RCE via torch.load)
> 2025-11-20 17:11:03,725 - modelaudit.scanners - DEBUG - Allowlisted safe global from potentially dangerous module: torch._utils._rebuild_tensor_v2
> 2025-11-20 17:11:03,725 - modelaudit.scanners - DEBUG - Check passed: Global Module Reference Check - Safe global reference validated: torch._utils._rebuild_tensor_v2
> 2025-11-20 17:11:03,725 - modelaudit.scanners - DEBUG - Allowlisted safe global from potentially dangerous module: torch.FloatStorage
> 2025-11-20 17:11:03,725 - modelaudit.scanners - DEBUG - Check passed: Global Module Reference Check - Safe global reference validated: torch.FloatStorage
> 2025-11-20 17:11:03,726 - modelaudit.scanners - DEBUG - Allowlisted safe global from potentially dangerous module: collections.OrderedDict
> 2025-11-20 17:11:03,726 - modelaudit.scanners - DEBUG - Check passed: Global Module Reference Check - Safe global reference validated: collections.OrderedDict
> 2025-11-20 17:11:03,726 - modelaudit.scanners - DEBUG - Check passed: REDUCE Opcode Safety Check - REDUCE opcode with safe ML framework global: collections.OrderedDict
> 2025-11-20 17:11:03,726 - modelaudit.scanners - DEBUG - Check passed: REDUCE Opcode Safety Check - REDUCE opcode with safe ML framework global: collections.OrderedDict
> 2025-11-20 17:11:03,727 - modelaudit.scanners - DEBUG - Check passed: Reduce Pattern Analysis - No dangerous __reduce__ patterns detected
> 2025-11-20 17:11:03,727 - modelaudit.scanners - DEBUG - Check passed: Opcode Sequence Analysis - No suspicious opcode sequences detected
> 2025-11-20 17:11:03,728 - modelaudit.scanners - CRITICAL - [CRITICAL] (/home/api-server/.modelaudit/cache/huggingface/ykilcher/totally-harmless-model/pytorch_model.bin:archive/data.pkl): CRITICAL: Malicious code detected: STACK_GLOBAL(1), GLOBAL(3), REDUCE(1) opcodes detected
>

After these logs, the process never exits, never writes the JSON output file, and does not return to the shell prompt.

The last lines before the hang are consistently:

> DEBUG - Check passed: Opcode Sequence Analysis - No suspicious opcode sequences detected
> CRITICAL - Malicious code detected: STACK_GLOBAL(1), GLOBAL(3), REDUCE(1) opcodes detected

Then the scan stops progressing.

installation method

> using standalone installation
> pip install modelaudit


  Fixed in modelaudit v0.2.18 

  Thanks for reporting this! We've identified and fixed the root cause of the hang.

  The scanner was running regex checks on model weight files, which caused scans to run for a very long time on certain models. We found a better way to validate the contents of weight files quickly, which resolves the hanging issue while still detecting all security threats.

  PyPI: https://pypi.org/project/modelaudit/0.2.18/

  ---
  Thanks again for reporting this! I would love to discuss how you're using modelaudit and understand your perspective on how we could improve it.

  Feel free to book some time on my calendar: https://cal.com/yash-chhabria/30min