mcpField
P
pkgtruth

pkgtruth

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

pkgtruth について

pkgtruthは、インストール前にnpmとPyPIの依存パッケージを検査するツールです。コーディングエージェント、CI、開発者向けに、MCPツール、コマンドライン、Claude Codeフック、GitHub Actionで架空またはリスクのある名前を検出します。

主な機能

  1. 01npmとPyPIのパッケージ名を検査
  2. 02マニフェストとインストールコマンドを確認
  3. 03なりすましやリスク要因を検出
  4. 04判定ごとに根拠を提示
  5. 05MCPサーバー、CLI、フック、Actionとして動作

活用シーン

  1. 01エージェントが提案した依存を導入前に確認
  2. 02CIでプロジェクトのマニフェストをスキャン
  3. 03Claude Codeで不審なインストールを阻止

MCP 対応

MCPサーバーとして、単一パッケージ、依存リスト、またはインストールコマンドを検査するツールを提供します。コーディングエージェントは依存を追加・導入する前に、結果と根拠を確認できます。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"hxckya-pkgtruth": {
"command": "npx",
"args": [
"-y",
"pkgtruth"
],
"env": {
"PKGTRUTH_REGISTRY": "<PKGTRUTH_REGISTRY>",
"PKGTRUTH_DOWNLOADS_API": "<PKGTRUTH_DOWNLOADS_API>",
"PKGTRUTH_CACHE_DIR": "<PKGTRUTH_CACHE_DIR>",
"PKGTRUTH_TIMEOUT_MS": "<PKGTRUTH_TIMEOUT_MS>"
}
}
}
}
起動コマンドnpx -y pkgtruth
設定が必要な環境変数
PKGTRUTH_REGISTRYAlternate npm registry to verify against. Defaults to https://registry.npmjs.org.
PKGTRUTH_DOWNLOADS_APIAlternate downloads API used for adoption figures. Defaults to https://api.npmjs.org.
PKGTRUTH_CACHE_DIRWhere adoption figures are cached between runs. Defaults to ~/.cache/pkgtruth.
PKGTRUTH_TIMEOUT_MSPer-request timeout in milliseconds. Defaults to 8000.

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

パッケージ
npmpkgtruth0.2.2

ツール

3

掲載時のツール一覧 · 2 週間前に更新

パラメーター型必須説明
namestringはいインストール時に使われる正確なパッケージ名。例: "express"、"@scope/pkg"、PyPI の場合は "requests"。バージョン接尾辞は付けません。
ecosystemenumいいえ照合するレジストリ。デフォルトは npm です。npm | pypi

詳細

pkgtruth

npm CI node license

AI コーディングエージェントと CI のための、npm と PyPI パッケージに関する確かな情報です。

pkgtruth が幻覚パッケージとスロップスクワットを検出する様子

エージェントが npm install unused-imports と書いたとします。そのパッケージは、エージェントが意図したリンタープラグインではありません。モデルが繰り返し作り出したため、攻撃者が登録した名前であり、npm はその後、セキュリティ用のプレースホルダーに置き換えました。

pkgtruth は、それがロックファイルに入る前に検出します。エージェントが問い合わせる MCP サーバーとして、CI 用の CLI として、プルリクエスト上で動く GitHub Action として、あるいはインストールコマンド自体を拒否する Claude Code フックとして利用できます。

なぜこれが必要なのか

大規模言語モデルはパッケージ名を作り出します。複数のモデルを対象とした測定では、生成されたパッケージ名の19.7%が幻覚によるものであり、研究者がプロンプトを再実行したところ、そのような名前の43%が毎回まったく同じように出力されました。

この再現性こそが、攻撃のすべてです。攻撃者はメンテナーを侵害したり、ビルドサーバーを汚染したり、脆弱性を見つけたりする必要はありません。モデルが何を作り出すかを監視し、その名前を登録して待つだけです。この手法はスロップスクワッティングと呼ばれ、すでに実際に起きています。

一般的なセキュリティ上の助言は、パッケージ管理機能を持つエージェントは、レビューの関門なしに何もインストールすべきではないというものです。pkgtruth は、その関門をエージェント自身が呼び出せる形で提供します。

実際に見つかった例

モデルがもっともらしく生成する名前が2つあります。どちらも現在 npm に存在します。

名前内容週間インストール数本来のパッケージ
types-node0.0.1-security — マルウェアの一掃後に npm が置いたプレースホルダー10@types/node (429M)
socket-io2022年から非推奨。「代わりに socket.io パッケージを使ってください」1,486socket.io (18M)

モデルが @types/node のスコープを省くと、types-node が出てきます。npm は2024年12月に悪意あるコードを理由に削除しましたが、今も週に10回インストールされています。

socket-io に悪意はありません。紛らわしい名前を持つ放置されたパッケージです。それでも週に1,486回インストールされていることが重要です。ドットとハイフンの違いだけで十分なのです。

PyPI にも同じ傾向がありますが、プレースホルダーはありません。

名前内容週間インストール数本来のパッケージ
sklearn非推奨の互換パッケージ。独自の通知に「代わりに scikit-learn を使ってください」と記載321,887scikit-learn (42.6M)
pytorch「PyTorch の名前が付いたパッケージは torch です」という内容しかないおとりパッケージ41,026torch (14.4M)

どちらも、本来のパッケージとは名前が似ても似つきません。そのため pkgtruth は、非推奨の通知に何と書かれているかも読み取ります。通知で挙げられたパッケージの人気がはるかに高ければ、その名前が証拠になります。

npx pkgtruth check types-node socket-io
npx pkgtruth check -e pypi sklearn pytorch

この2つは、20個の名前を手作業で確認した中から見つかりました。体系的な調査として、よく知られたパッケージ242個と、それぞれについて考えられるあらゆる誤記を毎週月曜日に再生成する取り組みを、SLOPSQUATS.md に掲載しています。そこのセクションAは、npm のセキュリティ用プレースホルダーだけを扱っています。npm がマルウェアを理由に削除したにもかかわらず、今週もインストールされている名前です。リストに名前が加わったり外れたりする週はリリースとして公開されるため、リリースフィードを使えば、リポジトリを監視せずに最新のリストを追えます。

インストール

MCP サーバーとして(コーディングエージェント向け)
{
  "mcpServers": {
    "pkgtruth": {
      "command": "npx",
      "args": ["-y", "pkgtruth"]
    }
  }
}

3 つのツールが利用可能になります。

ツール使用するタイミング
check_package依存関係を 1 つ追加、インポート、または推奨する前(ecosystem: "npm" | "pypi"、デフォルトは npm)
check_dependenciespackage.json / requirements.txt を作成する前
check_install_commandnpm install …、npx …、pip install … を実行する前 — コマンドをそのまま渡します
Claude Code フックとして(インストールコマンド自体を停止)

エージェントが MCP ツールを呼び出すのを忘れると、そのツールは役に立ちません。代わりに PreToolUse フックはすべてのシェルコマンドで実行され、指定されたパッケージが幻覚によるもの、または危険なものである場合、npm install、npx、 pnpm add、yarn add、bun add、pip install、uv add、poetry add などを拒否します。これを ~/.claude/settings.json(すべてのプロジェクト)または .claude/settings.json (単一リポジトリ。コミット可能)に追加してください。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": "npx -y pkgtruth hook" }]
      }
    ]
  }
}

名前を指定して何もインストールしないコマンド — 単独の npm install、git、テスト、 node_modules にすでにあるツールの npx <bin> — はネットワーク呼び出しなしで実行されます。 ブロックされたコマンドは、根拠を添えた拒否としてエージェントに返されるため、実在するパッケージを選べます。

pkgtruth blocked this command: 1 of 2 package(s) must not be installed as-is.
  ✖ crossenv DANGER — npm replaced this package with a security placeholder (0.0.2-security).
    The name was used to publish malicious code. Package is 1 edit(s) from "cross-env",
    which has 22,155,059 weekly downloads (15,418x this one). Confirm you meant this
    package and not that one.

検証できなかったパッケージも停止するには、--fail-on caution を追加します。 "command": "pkgtruth hook" を指定して npm install -g pkgtruth を実行すると、呼び出しごとの npx による解決をスキップできます(計測値:npx 経由でコマンドあたり約 0.2 秒、直接実行で約 0.03 秒)。フックは Claude Code の JSON から tool_input.command を読み取るか、コマンドをパイプで渡す他のエージェントからは単独のコマンド文字列を読み取り、ブロック時には permissionDecision: "deny" とともに終了コード 2 で終了します。エージェントは実行するコマンドの環境を制御できるため、無効化する環境変数はありません。

Claude Code プラグインとして(サーバーとフックをまとめてインストール)
/plugin marketplace add hxckya/pkgtruth
/plugin install pkgtruth@pkgtruth

プラグイン(plugin/)は、同梱された npm リリースに固定して、MCP サーバーと上記のフックをまとめて登録します。

CLI として(人間と CI 向け)
npx pkgtruth check express unused-imports          # npm (default)
npx pkgtruth check -e pypi requests sklearn        # PyPI
npx pkgtruth scan .                                 # every manifest in the directory

scan は package.json、requirements*.txt、pyproject.toml (PEP 621 と Poetry)を読み取り、それぞれを対応するレジストリでチェックします。ブロック対象があるとゼロ以外の終了コードを返すため、そのまま CI に組み込めます。

プルリクエストのゲートとして(GitHub Action)

hxckya/pkgtruth-action( GitHub Marketplace 上)はすべてのプルリクエストでスキャンを実行し、根拠を記載した固定コメントを 1 件投稿します。また、HALLUCINATED または DANGER の場合はチェックを失敗させます。

on:
  pull_request:
    paths: ['package.json', '**/package.json']
permissions:
  contents: read
  pull-requests: write
jobs:
  pkgtruth:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: hxckya/pkgtruth-action@v1

このリポジトリ自身もこのゲートを使用しています — .github/workflows/gate.yml を参照してください。意図的に不正なフィクスチャに対して実行することで、ゲートが失敗することも確認できます。

チェック内容

シグナル意味
レジストリに存在しない名前が捏造されています。インストールするものはありません。
npm セキュリティプレースホルダーnpm が、この名前で公開された悪意のあるコードを削除しました。
人気パッケージになりすましているほぼ同一の名前なのに利用実績がごくわずかです。または、意図したパッケージ名自体を記載した非推奨通知があります(sklearn → scikit-learn、pytorch → torch)。
取り下げ済み(PyPI)最新リリースのすべてのファイルが、メンテナーによって取り下げられています。
インストール時スクリプトpreinstall / install / postinstall は npm install 時にコードを実行します。
非推奨アップストリームが使用を中止するよう案内しています。
非常に新しい/利用実績がほとんどない公開から数日で、インストール数が一桁です。
リポジトリがない監査できるソースがありません。
メンテナンスされていない何年もリリースされていません。

判定は SAFE、CAUTION、DANGER、HALLUCINATED、UNKNOWN のいずれかです。 どの判定にも根拠が付属するため、エージェントが「DANGER」を盲信する必要はありません。あなたも同様です。

設計上の注意点

ネットワーク障害があっても、決してゲートを開きません。 レジストリに接続できない場合、判定はSAFEではなく、必ずUNKNOWNになります。ネットワークの劣化によって、セキュリティチェックが暗黙のうちに無効化されてはなりません。

人気のあるパッケージにはフラグを立てません。主張ではなく、測定に基づいています。 誤検知監査では、よく知られた240個のパッケージの直接依存関係の全体に対して検出器を実行します。組み込みの2回目のチェック後の結果は、実在するパッケージ1,523個、ブロッキング判定0件、UNKNOWN 0件、そしてCAUTIONが40件(非推奨またはメンテナンスされていないパッケージ。事実に基づく判定であり、デフォルトではブロックされません)です。誤警報を出すゲートは無効にされてしまいます。このゲートには、その根拠となる数値があります。

ビルド手順は不要です。 直接依存関係は2つ、MCP SDKとzodだけです。どちらもサーバーにのみ必要です。npx pkgtruthですぐに起動できます。

制限事項

信頼する前に、以下をお読みください。

  • 対応しているのはnpmとPyPIのみです。 crates.io、Go modules、RubyGemsにはまだ対応していません。
  • PyPIには削除済みを示すマーカーがありません。 npmではマルウェアを削除した場所に-securityプレースホルダーが残りますが、PyPIではプロジェクト自体が削除されるため、削除されたPyPIの名前は単にHALLUCINATEDとして扱われます。また、PyPIには検索APIがありません。類似した名前は、ダウンロード数上位15,000プロジェクトの日次スナップショットと照合して見つけるため、知名度の低いパッケージを装った偽物は検出できません。
  • レジストリのメタデータのみを対象とします。 パッケージのソースコードは解析しないため、正規に見えるパッケージでも、悪意のあるペイロードが含まれていれば検査を通過する可能性があります。
  • npm auditやSnykの代替ではありません。 これらは、すでに信頼しているコードに含まれる既知のCVEを検出します。pkgtruthが問うのは、それより前の問い、つまり「そもそもこのパッケージをここに置いてよいのか」です。
  • 新しい正規パッケージにはCAUTIONが付与されます。 これは意図的な動作です。新しさは実際にリスクを示すシグナルです。ブロックされないようにするには、--fail-on dangerを使用してください。

オプション

--json              Machine-readable output
--fail-on <level>   danger (default) | caution

--fail-on cautionでは、まったく検証できなかったパッケージもブロックされます。「確認できなかった」は合格を意味しないためです。

終了コード:0 問題なし、1 ブロック対象のパッケージが見つかった、2 使用方法または実行時のエラー。

設定

変数デフォルト用途
PKGTRUTH_TIMEOUT_MS8000リクエストごとのタイムアウト
PKGTRUTH_RETRIES3429/5xx/ネットワークエラー発生時の再試行回数
PKGTRUTH_MAX_CONCURRENCYホストごとリクエストの送信間隔を上書き
PKGTRUTH_REGISTRYnpm代替レジストリ
PKGTRUTH_DOWNLOADS_APInpm代替ダウンロードAPI
PKGTRUTH_PYPI / PKGTRUTH_PYPISTATSpypi.org / pypistats.org代替PyPIエンドポイント
PKGTRUTH_PYPI_TOPhugovk top-pypi-packagesPyPIの類似パッケージ検索に使う、代替の人気度スナップショット
PKGTRUTH_CACHE_DIR~/.cache/pkgtruth利用状況の数値をキャッシュする場所
PKGTRUTH_DISK_TTL_MS6時間キャッシュされた数値を利用できる期間
PKGTRUTH_NO_DISK_CACHE未設定キャッシュを無効にするには1を設定
速度とレート制限について

利用状況の数値はnpmのダウンロードAPIから取得します。このAPIは短時間の大量リクエストを制限し、スコープ付きの名前をまとめて処理できません。そのため、複数の@scope/pkg依存関係を持つプロジェクトを毎回スキャンすると、利用枠をすべて使い切ってしまいます。

これを抑えるために、3つの対策を講じています。一括エンドポイントでスコープなしの名前を1回のリクエストで解決し、そのホストへのリクエストを順番に送信し、数値を6時間ディスクにキャッシュします。週間ダウンロード数の変動は小さいため、6時間前の数値も最新のものと変わらず正確です。

依存関係が約18個の場合、キャッシュが温まった状態でのスキャンには約1.4秒かかります。大規模なスキャンでダウンロードAPIから429が返されると、初回のチェックでは一部のパッケージがUNKNOWNになります。その場合、すべてのエントリーポイントで、短い待機時間を挟んだ後、該当する名前だけを順番に再チェックします。1,523個のパッケージを対象とした監査では、この2回目のチェックですべてが解決されました。レート制限によって、照会結果がSAFEになることはありません。

キャッシュされた数値は取得元のAPIごとに識別されるため、PKGTRUTH_DOWNLOADS_APIをプライベートレジストリに向けても、npmの数値が再利用されることはありません。

コントリビューション

github.com/hxckya/pkgtruth で、Issue やプルリクエストを歓迎します。

特に有用な報告は、正当なパッケージが誤検知されたケースと、悪意のあるパッケージが検出をすり抜けたケースです。どちらも、回帰テストとして追加する価値があります。

npm test                 # offline
npm run test:online      # includes live registry checks

ライセンス

MIT © hxckya

コメント

MCP は初めてですか?

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

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