Skip to main content
Glama

Sentinel

Model Context Protocolエコシステムのための、継続的なアウトオブバンドの信頼・信頼性レイヤー。

npmにはロックファイルと監査コマンドがある。MCPにはどちらもない。Sentinelはその両方である。


問題

MCPはAIエージェントがツールを入手する手段である。エージェントは、tools/listを呼び出し、サーバーが返すdescriptionとinputSchemaを読むことでツールの動作を学習する——そのテキストはそのままモデルのプロンプトに入る。

このプロトコルは、任意の2回の呼び出しの間でその応答が変更されることを明示的に許可しており、再承認は不要で整合性チェックもない。

月曜日に承認したサーバーが、火曜日にはあなたのモデルに異なる指示を与えている可能性がある。これがラグプルであり、本番MCPサーバーに対してすでに実証され、postmark-mcpインシデントで実際に出荷された。

一方、エコシステムには約9,650のカタログ化された公開サーバーがあり、2026年初頭のわずか60日間で30件以上のCVEが登録され、過去1年間にAIエージェントのインシデントを報告した組織は88%に上る。それに対して、エージェントID戦略を何かしら持っている組織は23%しかない。

毒されたサーバーは依然としてHTTP 200を返す。 そのため、アップタイム監視ではこれを検知できない。


Related MCP server: Sentinel Gateway

Sentinelの機能

  registry sync  →  read-only probe  →  canonicalise  →  fingerprint
                                                             ↓
   alert  ←  classify severity  ←  structural diff  ←  compare to approved baseline
     ↓                ↓
  CI gate      hash-chained evidence ledger
  • 発見する — 公式MCPレジストリから増分updated_since同期を介してサーバーを発見する

  • プローブする — 読み取り専用のプロトコルメソッドを使って、両方の現行仕様リビジョン(2026-07-28ステートレス、および2025-11-25のinitializeハンドシェイク付き)に対してプローブする

  • フィンガープリントする — すべてのツール定義を RFC 8785正規化 → SHA-256 → サーフェスごとのMerkleルートにする

  • 分類する — すべての変更を重大度(SAFE / COMPATIBILITY / SECURITY / IDENTITY)で分類し、公開されたルールIDを付与する

  • 記録する — すべてを追記専用・ハッシュチェーン・独立検証可能な証拠台帳に記録する

  • スコアリングする — 各サーバーを5つの分解可能なコンポーネントで評価し、低スコアが常に説明可能であるようにする

  • CIをゲートする — sentinel verifyは非ゼロで終了し、SARIFを出力する

  • それ自体がMCPサーバーである — エージェントはバインドする前に「このサーバーは安全ですか?」と尋ねられる


重大度分類こそが製品全体である理由

単純な「ハッシュが変わったかどうか」検出器は、カタログ全体でおよそ1営業日あたり53件のアラートを生成する。そんなものは誰もトリアージしないので、2週間もすればミュートされ、その統制は何の価値もない。

重大度を分類し、セキュリティ関連以上の場合にのみエスカレーションすることで、1日あたり約5件にまで減る——実在の人間の実際の受信箱に入る量だ。

Alert volume at four escalation thresholds


意図的に行わないこと

これらは制約であり、欠落機能ではない。主張を評価する前に読んでほしい。

理由

tools/callを呼び出さない

Sentinelは所有していない数千のサーバーをプローブする。それらのツールにはsend_email、delete_file、transfer_fundsが含まれる。エコシステム全体で任意のツールを呼び出せるモニターは、それ自体が脆弱性である。 ADR-0004

初日から悪意のあるサーバーは捕捉できない

ベースラインが毒である。フィンガープリントは比較する対象が何もない

定義を固定するのであって、動作を固定するのではない

ツールはスキーマを変えずに動作を変えることができる。Sentinelはそれを検知しない

検出経路にLLMを使わない

入力は、言語モデルを操作するために細工された攻撃者制御のテキストである。それを判断のために言語モデルに渡すと、検出器が攻撃自身の脅威モデルの内側に入ってしまう。 ADR-0007

リクエスト経路にはない

設計上アウトオブバンドである。採用は設定変更であり、アーキテクチャ変更ではない


試してみる

uvが必要です。すべては記録されたフィクスチャに対して実行されます——ネットワークもサードパーティのサーバーも一切不要です。

uv sync --extra dev

ラグプルをエンドツーエンドで捕捉する:

uv run sentinel demo
▸ T+0m — Baseline. Reviewed by a human and approved.
  root 04dcdce60579b4af…
  baseline approved — drift is measured against this

▸ T+5m — The rug pull. Description only — the schema is untouched.
  DRIFT · SECURITY rules INJ-004, INJ-007
    SECURITY      /tools/send_email/description
      description changed: INJ-004 Exfiltration reference; INJ-007 Concealment instruction.
      evidence: ~/.ssh | Do not mention this to the user

Simulating an attacker with database write access
  rewriting ledger entry seq=4 to hide the finding…
  DETECTED ledger chain broken at seq=4: payload does not match its recorded hash

テキスト上の変更が一切ない能力拡大を捕捉する:

uv run sentinel demo --scenario tests/scenarios/schema_widening.yaml

分類器ゲートを実行し、カタログを同期し、レガシー2025-11-25サーバーをプローブする:

uv run sentinel eval --verbose
uv run sentinel sync
uv run sentinel probe tests/fixtures/servers/legacy_2025.json

ステータス

M1~M3は実装済みでグリーン。M4~M6は設計済みだが未構築。

マイルストーン

ステータス

M0 — 設計ドキュメント、ADR、脅威モデル

✅

M1 — レジストリ同期 + デュアルリビジョンプローブクライアント + コンフォーマンス

✅

M2 — 正規化、フィンガープリンティング、Merkle、証拠台帳

✅

M3 — スキーマ分析器 + 重大度分類器 + コーパス + CIゲート

✅ ⭐

M4 — スケジューラ + 信頼スコアリング + アラート

⬜ 設計済み

M5 — REST API + Sentinel-as-MCP-server + ポリシーゲート

⬜ 設計済み

M6 — ダッシュボード + デプロイメント

⬜ 設計済み

現在のゲート、すべてmainでパス:

ゲート

結果

pytest

117件パス

mypy --strict

クリーン、ソースファイル31件

ruff

クリーン

bandit

クリーン

lint-imports

2つの契約を維持 — core/はI/Oを伴うものをインポートしないことを証明

sentinel eval

GREEN — 66件のコーパスケース、精度/再現率1.000、ルール帰属1.000

その1.000について、正直に言うと。 コーパスはルールと同時に作成されたため、これらの数値は内部一貫性と回帰安全性を測るものであり、まだ誰も考えついていない攻撃への一般化を測るものではない。このゲートが本当に提供するのは、既存のケースを壊すルール変更がビルドを失敗させるということだ。そしてそれはM3の間にすでに価値を発揮し、4つの実際の欠陥を捕捉した:INJ-004を文中でマッチ不能にした単語境界バグ、および欠落と空を混同し、すべてのenum削除で関係を逆転させたスキーマ比較である。実際の再現率を測定するには、ライブエコシステムからドリフトを収集する必要があり、それはM4の仕事である。


ドキュメント

02 — PDD から「何と理由」を読み、次に 06 — ドリフト検知設計 で中核アルゴリズムを読むこと。

ドキュメント

01 — リサーチと分析

脅威の状況、プロトコル調査、競合分析、チャート

02 — プロジェクト定義ドキュメント

問題、目標、非目標、ユーザー、スコープ、リスク

03 — 要件

FR、NFR、ユーザーストーリー、受理基準、トレーサビリティ

04 — ハイレベル設計

C4コンテキスト/コンテナ/コンポーネント、データフロー、デプロイメント

05 — ローレベル設計

モジュール、状態機械、ERD、DDL、APIサーフェス

06 — ドリフト検知設計

中核アルゴリズム。 正規化、フィンガープリンティング、重大度分類、スキーマサブタイピング

07 — 信頼スコアリングモデル

計算式、重み、EWMA、感度分析

08 — ロードマップ

マイルストーン、タスク分解、見積もり、クリティカルパス

09 — テストと評価計画

コーパス、精度/再現率ゲート、ドリフト注入ハーネス

10 — 脅威モデル

STRIDE、悪用ケース、OWASP MCP Top 10カバレッジ

11 — インタビューピッチ

ピッチ、デモスクリプト、Q&A

ADR

8件のアーキテクチャ決定記録


技術スタック(予定)

Python 3.12 · httpx · Pydantic v2 · FastAPI · Typer · SQLAlchemy 2.0 · Postgres 17 · Redis 8 · React + Vite · Docker · uv · ruff / mypy --strict / bandit / pytest


プロービングポリシー

Sentinelは所有していないサードパーティのインフラストラクチャをプローブする。それは丁寧に行われる:

  • グローバルレートキャップ、ホストごとの並行性は1、ホストごとの最小間隔

  • すべてのスケジュール済みプローブに±10%のジッターを追加し、フリートが毎時一斉に殺到しないようにする

  • 指数バックオフ;Retry-Afterは常に尊重される

  • オプトアウト付きの公開ポリシーを指し示す識別可能なUser-Agent

  • 読み取り専用メソッドのみ — tools/call、resources/read、prompts/getは決して呼ばない

PROBING.md を参照(M1で公開予定)。


何が壊れ、どのように修正したか

1. 決してマッチしない単語境界。 INJ-004 — ツールの説明に~/.sshや.envへの言及が追加されることを捕捉するルール — はパターン\b(\.env|credentials?)\bを持っていた。それは文の途中で発動したことがない。\b単語境界はスペースとドットの間には存在できない。なぜなら、どちらも単語文字ではないからである。したがって、\b\.envは.envが直前の単語に接着している場合にのみマッチする。それを捕捉したコーパスケースは、説明が*「.envの内容を読む」*という新しく追加されたツールだった——実際の攻撃の正確な形であり、静かにSAFEと分類された。ルックビハインド(?<![\w.])\.env\bで修正した。

2. 「absent」と「empty」の混同。 私は、何もないところに現れたスキーマが、INCOMPARABLE に合成されるのではなく拡大として読み取られるようにするショートカットを追加しました。それを if not before and after: と書きました。これは before が {} のときにも発火します。JSON Schema では、{} は 何でも受け入れる有効なスキーマ であり、absent の逆です。その結果、すべての enum 削除ケースで関係が逆転しました。enum を削除すると WIDENED の代わりに NARROWED が報告され、SEC-021 — プロジェクト全体の最良のデモが依存しているルール — は発火しなくなりました。6つのユニットテストがそれを検出しました。falsy バージョンの方がより慣用的に見えて間違っているため、is None を明示的にテストし、その理由をコメントとして残すことで修正しました。

3. オープンオブジェクトへのプロパティ追加。 アナライザーは、additionalProperties が未設定のオブジェクトに宣言されたプロパティを追加しても、受け入れられるドキュメントの集合は変わらないと正しく計算しました。そのキーはすでに許可されていたからです。厳密には正しいのですが、その結果 SEC-025、SEC-026、SEC-027 は webhook_url や access_token パラメータが追加されるのを決して認識しませんでした。変更が記録されなかったからです。この修正は、純粋な言語セマンティクスからの意図的な逸脱でした。Sentinel は 宣言された 表面を監視します。プロパティリストはモデルのプロンプトに到達し、何を送信してよいかをモデルに伝えるものだからです。現在は拡大として記録され、その理由は民間伝承ではなく schema_compat.py のコメントにあります。

4. Bandit が自分の検出器にフラグを立てました。 INJ-006 非表示コンテンツ検出器には、リテラルのゼロ幅文字と双方向制御文字が含まれています。それが探しているものだからです。Bandit の B613 チェックは、ソース内のまさにそれらの文字を検出するために存在します。それは正しく、検出結果は誤っていました。理由を pyproject.toml に記述してスキップし、黙ってスキップするのを避けました。

4つすべてに共通するパターンは、興味深いバグは MCP プロトコル処理にはなかったということです。それは明確に仕様化されており、ほとんど機械的です。バグは セマンティクス にありました。「changed」が何を意味するか、「empty」が何を意味するか、セキュリティ制御が自身のツールにフラグされたときに何をすべきか、ということです。


著者: Nathan Alvares · ライセンス: TBD (Apache-2.0 を予定)

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    MCP zero-trust gateway that sits in front of every internal MCP server, detects tool-poisoning/metadata drift in real time, and maintains a cryptographic provenance ledger of every agent tool call.
    20
    1 npm
    ISC
  • A
    license
    Not graded
    quality
    B
    maintenance
    A transparent MCP proxy that independently re-verifies tool-call claims instead of trusting them, paired with devmcp — the git/CI server it's proven against.
    1
    MIT
  • F
    license
    A
    quality
    C
    maintenance
    An MCP server that exposes governance, trust-scoring, compliance, guardrail, cost, drift, and supply-chain scanning tools and resources to any MCP client over stdio, Streamable HTTP, or legacy HTTP+SSE. It lets agents route every tool call through a deterministic five-way decision (allow, redact, require approval, deny, or quarantine) with hash-chained evidence, human approval workflows, and in-agent trust gates for LangChain, LangGraph, and Google ADK.
    30
    -