mcp-tenant-isolation について
mcp-tenant-isolationは、マルチテナントSaaSやMCPサーバーのコードを静的解析し、テナント境界の不足を検査します。57件の決定論的ルールで構造化された検出結果を出力し、ローカルMCPサーバーとしてエージェントからのスキャンにも対応します。
主な機能
- 0157件のルールでテナント分離を検査
- 02データベース、キャッシュ、ファイル、APIをカバー
- 03TypeScript、JavaScript、Prisma、SQLに対応
- 04JSON、SARIF、Markdown形式でレポート
- 05ベースラインで修正状況を追跡
活用シーン
- 01リリース前にSaaSのテナント間漏えいを確認
- 02MCPツールのテナントアクセス制御をスキャン
- 03CI/CDで分離チェックを実行
MCP 対応
ローカルのstdio MCPサーバーとして動作し、プロジェクトのスキャン、ルール一覧・説明、検出結果の任意の抑制を提供します。書き込みを伴う抑制ツールは、明示的に有効化するまで非表示です。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
3掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| path | string | いいえ | スキャンするプロジェクトルートのパス。許可されたプロジェクトルート内である必要があります。省略した場合は、許可されたルート自体をスキャンします。 |
| rules | string | いいえ | 実行するルール ID(カンマ区切り、空欄 = すべて) |
| severity | enum | いいえ | 重大度の最低フィルターLOW | MEDIUM | HIGH | CRITICAL |
詳細
mcp-tenant-isolation
マルチテナントの SaaS および MCP サーバーのコードを対象とした静的解析スキャナーです。本番環境に到達する前に、テナント間のデータ漏えいを検出する 57 個の決定論的なルールを備えています。
できること
マルチテナントのソフトウェアを構築する場合、すべてのクエリ、キャッシュキー、ファイルアクセス、API レスポンスを適切なテナントに紐づける必要があります。一つでも見落とすと、テナント A がテナント B のデータを見てしまいます。本番環境で見つけたい不具合ではありません。
このスキャナーはソースコードを読み込み、必要な箇所にテナント分離のガードがあるかを確認します。データベースクエリ、API ルート、キャッシュキー、ファイルストレージ、スキーマ設計、ログ記録、MCP サーバーのアーキテクチャにわたる 57 個のパターンを対象としています。TypeScript、JavaScript、Prisma、Drizzle、raw SQL、Next.js、Express、Fastify に対応しています。
スキャナーは MCP サーバーとしても実行できるため、Claude Desktop、Cursor、または MCP 互換のエージェントに接続して、必要に応じて AI アシスタントにコードをスキャンさせることができます。
利用者
- SaaS エンジニアリングチーム:コードのリリース前にテナント分離の不備を検出したいチーム
- MCP サーバー開発者:テナント単位のデータを扱うツールを構築する開発者
- セキュリティチーム:CI/CD にテナント分離チェックを組み込みたいチーム
- AI エージェント開発者:エージェントにコードをスキャンさせ、テナント間のリスクを検出したい開発者
開発の背景
汎用のセキュリティスキャナーは、テナント分離のパターンに特化していません。SQL インジェクションや XSS は検出しますが、findMany クエリに organizationId フィルターが含まれているかは確認しません。MCP ツールのハンドラーがテナントごとにツールの可視性を制限しているかも確認しません。キャッシュキーにテナントのプレフィックスが含まれているかも確認しません。
このスキャナーは、まさにその点を検査します。57 個のルールがそれぞれ特定のテナント分離パターンを確認し、ルール ID、ファイル、行、欠落しているガード、修正のヒントを含む検出結果を出力します。
すべてのルールは決定論的です。同じソースコードに対して、スキャナーは常に同じ検出結果を出力します。機械学習も確率的なスコアリングも使用しません。ただし、静的解析には本質的な限界があります。実行時の動作、データベースレベルの強制、動的なテナント分離は検証できません。スキャン出力には limitations フィールドがあり、各実行で確認した内容と確認していない内容を一覧表示します。
インストール
npm install -g mcp-tenant-isolation
# or use npx (no install needed)
npx mcp-tenant-isolation scan ./src
# or use Docker (no Node.js needed)
docker run --rm -v $(pwd):/code subodhkc/mcp-tenant-isolation scan /code/src
Node.js 22 以降が必要です。
クイックスタート
mti scan ./src
mti scan ./src --format sarif --output results.sarif
mti scan ./src --format markdown --output TENANT-ISOLATION-REPORT.md
mti scan ./src --format ai --output findings.json
mti scan ./src --severity HIGH
mti rules # list all 57 rules
mti baseline # snapshot current findings for proof-of-fix tracking
mti init # create .mtirc.json with defaults
デモ
ルール
汎用マルチテナントルール 42 件
| Prefix | Category | Count | Severity | What it checks |
|---|---|---|---|---|
| TCM | テナントコンテキスト管理 | 6 | Critical | テナント ID がクライアント入力ではなくセッションから取得されていること。非同期処理の境界を越えてコンテキストが伝播されること。 |
| DBQ | データベースクエリの分離 | 10 | Critical | テナントスコープのデータにアクセスするすべてのクエリに、テナントフィルターが含まれていること。Prisma、Drizzle、raw SQL が対象です。 |
| IDOR | IDOR の防止 | 5 | Critical | ID による検索で、データを返す前にテナントの所有権を検証していること。 |
| CSI | キャッシュとセッションの分離 | 4 | High | キャッシュキーとセッションデータがテナントスコープになっていること。 |
| API | API セキュリティ | 3 | High | テナントを考慮したレート制限とレスポンスのスコープ設定が行われていること。 |
| FSI | ファイルストレージの分離 | 4 | High | S3、Blob、ファイルシステムへのアクセスがテナントスコープになっていること。 |
| LOG | ロギングと監査 | 4 | Medium | 監査ログにテナントコンテキストが含まれていること。 |
| SCH | スキーマとマイグレーション | 6 | High | Prisma モデルと SQL マイグレーションにテナント列とインデックスが含まれていること。 |
MCP 固有のルール 15 件
| ID | タイトル | 重大度 | チェック内容 |
|---|---|---|---|
| MCP-001 | ツールの可視性スコープ設定 | Critical | ツールハンドラーにテナントベースの許可/拒否フィルターがないこと。 |
| MCP-002 | キャッシュキーのテナントプレフィックス | Critical | ツールの結果がテナントプレフィックスなしでキャッシュされていること。 |
| MCP-003 | セッションとユーザー+テナントの紐付け | Critical | セッション ID のみを認可に使用していること。 |
| MCP-004 | トークン交換(RFC 8693) | High | トークン交換ではなく、元のトークンが転送されていること。 |
| MCP-005 | テナントごとのレート制限 | Medium | ツール呼び出しにテナントごとのレート制限がないこと。 |
| MCP-006 | ベクトルストアのテナント名前空間 | High | テナント名前空間のない共有ベクトルストアを使用していること。 |
| MCP-007 | ツールの説明へのインジェクション | Medium | ツールの説明によって分離を回避できる可能性があること。 |
| MCP-008 | 認証情報ボルトのテナントスコープ設定 | Critical | 認証情報ボルトにトークンがテナントスコープなしで保存されていること。 |
| MCP-009 | 共有サービスアカウント | High | すべてのテナントの API 呼び出しに単一の共有 API キーが使われていること。 |
| MCP-010 | 切断時のセッションクリーンアップ | Medium | セッションが確実にクリーンアップされないこと。 |
| MCP-011 | テレメトリのテナント識別子 | Low | テレメトリからテナント識別子が削除されること。 |
| MCP-012 | ローカルバインド(127.0.0.1) | High | MCP サーバーが 127.0.0.1 ではなく 0.0.0.0 にバインドされていること。 |
| MCP-013 | ファイルシステムのテナントルート | High | ツールハンドラーがテナントルートなしでファイルシステムにアクセスすること。 |
| MCP-014 | テナント間のアーティファクト漏えい | High | アーティファクトストレージにテナントプレフィックスがないこと。 |
| MCP-015 | 動的ツール名前空間 | Medium | テナント名前空間なしでツールが登録されていること。 |
MCP ルールは OWASP MCP Top 10(2025)に対応付けられています。対応付けの全容については、docs/OWASP-MAPPING.md を参照してください。この対応付けは、トリアージとレポート作成のための参考情報です。このスキャナーは OWASP 準拠を認証するものではありません。
アーキテクチャ
スキャナーパイプラインは次の 6 段階で実行されます。
- パーサー — TypeScript/JavaScript 用 Babel AST、Prisma スキーマパーサー、SQL マイグレーションパーサー、MCP SDK インポート検出
- IR とフローグラフ — ソース、シンク、ガード、ルート、MCP ツール定義を取得する中間表現
- ルールエンジン — IR に対して評価される 57 件の決定論的ルール。各ルールはソース、シンク、必須のガードを定義します
- 誤検知フィルター — テストファイルの検出、信頼度のスコアリング、パターンの調整
- レポーター — ターミナル、JSON、SARIF 2.1.0、修正のヒントを含む AI 向け JSON、Markdown
- CLI と MCP サーバー — scan/init/rules/suppress/baseline/mcp コマンドを備えた
mtiCLI。MCP サーバーは 4 つのツールを公開します
構造化出力
スキャン結果には、検出事項だけでなく、次の構造化メタデータも含まれます。
- 完全性 — COMPLETE、PARTIAL、ERROR のいずれかです。ファイルの解析に失敗した場合や、ルールの評価に失敗した場合は完全性が PARTIAL になり、その理由が一覧表示されます。
- カバレッジ — 検出、解析、解析失敗したファイルの数。利用可能、選択、評価、評価失敗、検出されたルールの数。未対応のファイル形式もカウントされます。
- 懸念事項の分類 — 検出事項は、トリアージ用に 8 つの懸念事項の分類(テナントコンテキスト、データ分離、キャッシュとセッション、MCP セキュリティ、シークレットと認証情報、ベクトルとストレージ、API とアクセス、監査とログ)にグループ化されます。
- 制限事項 — スキャンで検証できた内容と、できなかった内容です。常に静的解析の制限事項が含まれます。フロー解析の範囲と修正証明のステータスも含まれます。
- スキャンレシート — エンジンのバージョン、ルールパックのダイジェスト、タイムスタンプ、改ざん検出用の SHA-256 レシートハッシュを含む来歴メタデータです。
- 修正証明 — 各検出事項には、ベースラインファイルと比較した STILL_PRESENT、NEW、NOT_VERIFIABLE のいずれかのタグが付けられます。
mti baselineを実行してベースラインを作成してください。
フィンガープリント
検出事項には、行の移動やフォーマットの変更に影響されない、安定した v2 セマンティックフィンガープリントが使用されます。フィンガープリントは、ルール ID、ファイルパス、正規化されたコードスニペット、ソート済みの不足ガードから生成されます。行番号は含まれません。つまり、意味を変えずにコードを移動してもフィンガープリントは変わらず、ベースラインの追跡精度が維持されます。
MCP サーバー
このパッケージには、AI エージェントとの統合用の MCP サーバーが含まれています。stdio トランスポートを介してローカルで動作します。ホスティングやネットワークへの公開は不要です。
{
"mcpServers": {
"tenant-isolation": {
"command": "npx",
"args": ["-y", "mcp-tenant-isolation", "mcp"]
}
}
}
この設定を Claude Desktop、Cursor、Windsurf、またはその他の MCP クライアント設定に追加すると、AI エージェントが必要に応じてコードのテナント分離に関する問題をスキャンできるようになります。
MCP ツール
| ツール | 説明 | 書き込み? |
|---|---|---|
scan_tenant_isolation | プロジェクトのパスをスキャンします。完全性、カバレッジ、懸念事項の分類、レシートを含む構造化された検出結果を返します。 | いいえ |
list_tenant_isolation_rules | メタデータ付きで 57 個すべてのルールを返します。カテゴリでフィルタリングできます。 | いいえ |
explain_tenant_isolation_rule | ルールの詳細、OWASP のマッピング、CWE ID、修正案を返します。 | いいえ |
suppress_tenant_isolation_finding | 理由、承認者、対策、有効期限を指定して抑制を追加します。 | はい(オプトイン) |
抑制ツールはデフォルトでは非表示です。サーバーを --allow-write-tools を指定して起動した場合にのみ表示されます。これはセキュリティ境界です。デフォルトは読み取り専用で、書き込み操作には明示的なオプトインが必要です。
MCP スキャン中のすべてのファイルシステム操作は、サーバー起動時に設定されたプロジェクトルート内に制限されます。トラバーサル攻撃(../)、ルート外の絶対パス、UNC パス、シンボリックリンクによるルート外へのアクセスは拒否されます。詳細は SECURITY.md を参照してください。
CI/CD 統合
オプション 1:ビルド済みの GitHub Action(最も簡単)
これを .github/workflows/tenant-isolation.yml に追加してください。
name: Tenant Isolation Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: subodhkc/mcp-tenant-isolation@v2
with:
path: ./src
severity: HIGH
fail-on: HIGH
スキャンを実行し、SARIF を GitHub Code Scanning にアップロードして、Markdown レポートのアーティファクトを生成します。HIGH または CRITICAL の検出事項が見つかった場合、ワークフローは失敗します。
オプション 2:npx を手動で実行
name: Tenant Isolation Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npx mcp-tenant-isolation scan ./src --format sarif --output results.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
終了コード
| コード | 意味 |
|---|---|
| 0 | 検出事項なし |
| 1 | 検出事項あり |
| 2 | エラー(設定が無効、解析失敗など) |
GitHub Code Scanning との統合
github/codeql-action/upload-sarif@v3 を使用して SARIF 出力をアップロードすると、リポジトリの Security > Code scanning alerts タブに検出結果が表示されます。これは無料のリポジトリと、Advanced Security が有効なリポジトリの両方で機能します。
処理の流れ:
mti scan --format sarif --output results.sarifで SARIF 2.1.0 ファイルを生成しますupload-sarifアクションが GitHub のコードスキャン API にファイルを送信します- 各検出結果が、ファイル、行、重要度、修正のヒントを含むコードスキャンアラートになります
- アラートは GitHub UI から直接、却下、修正、または追跡できます
- プルリクエストの注釈が変更されたファイルに自動的に表示されます
要件:
- ワークフローに
permissions: security-events: writeを設定すること - アップロード手順の前に SARIF ファイルを生成すること
設定
プロジェクトのルートに .mtirc.json を作成します:
{
"rules": {
"severity": {
"DBQ-001": "HIGH",
"MCP-001": "CRITICAL"
},
"exclude": ["DBQ-010"]
},
"paths": {
"include": ["src/**/*"],
"exclude": ["**/*.test.ts", "**/*.spec.ts"]
},
"suppressions": ".mti-suppressions.json",
"baseline": ".mti-baseline.json"
}
高度な設定
{
"rules": {
"severity": { "DBQ-001": "HIGH" },
"exclude": ["DBQ-010"]
},
"paths": {
"include": ["src/**/*"],
"exclude": ["**/*.test.ts"]
},
"output": "terminal",
"framework": "nextjs-app-router",
"authHelpers": ["requireAuth", "getServerSession", "withAuth"],
"tenantGuards": ["organizationId", "tenantId", "workspaceId"],
"modelScopes": {
"userScoped": ["User", "UserSession"],
"global": ["Tenant", "AuditLog"]
},
"rulePacks": ["./custom-rules.json"],
"suppressions": ".mti-suppressions.json",
"baseline": ".mti-baseline.json"
}
| フィールド | 説明 |
|---|---|
output | デフォルトの出力形式:terminal、json、sarif、ai、markdown |
framework | フレームワークのヒント:nextjs-app-router、nextjs-pages、express、fastify、auto |
authHelpers | 検出するカスタム認証関数名(誤検知を減らします) |
tenantGuards | デフォルト以外に使用するカスタムテナントガード変数名 |
modelScopes | モデルのスコープ分類(userScoped、global、tenantScoped)を上書きします |
rulePacks | カスタムルールパック JSON ファイルへのパス |
カスタムルールパック
JSON 形式のルールパックを使って、スキャナーを拡張できます。カスタムルールは読み込み時に検証されます:
- ルール ID は
PREFIX-NNN形式(例:CUST-001)に一致する必要があります - ルール ID は組み込みルールと重複できません
- 重要度は INFO、LOW、MEDIUM、HIGH、CRITICAL のいずれかである必要があります
- すべてのルールパックを合わせたカスタムルール数は最大 50 件です
- ルールパックのパスはプロジェクトのルート内に制限されます(MCP モード)
無効なカスタムルールは警告とともに拒否されます。スキャンは組み込みルールを使って続行されます。
抑制
抑制には、具体的な検出結果のフィンガープリント、ルール ID、承認者を示す記録済み識別子、理由、代替コントロール、有効期限が必要です。ルール全体を対象とする抑制(フィンガープリントなし)が許可されるのは、記録された恒久的な例外に限られます。
documentedApprover フィールドには、抑制を承認した人が記録されます。これは独立した人間による検証を意味するものではありません。外部レビューを受けたという主張ではなく、承認者を記録する文字列です。
ベースライン
mti baseline を実行して、現在の検出結果のスナップショットを作成します。以降のスキャンではベースラインと比較し、各検出結果に STILL_PRESENT、NEW、または NOT_VERIFIABLE(ベースラインがない場合)のタグが付けられます。これにより、修正状況を長期にわたって追跡できます。
レポート形式
| 形式 | フラグ | 用途 |
|---|---|---|
| Terminal | --format terminal(デフォルト) | 合否判定を含む開発者コンソール |
| JSON | --format json | プログラムからの利用、ほかのツールへのパイプ |
| SARIF | --format sarif | GitHub Code Scanning、Azure DevOps |
| AI JSON | --format ai | 修正のヒントとコンテキストを含む AI エージェントでの利用 |
| Markdown | --format markdown | プルリクエスト、チームレビュー、ドキュメント用の共有可能なレポート |
# Generate a Markdown report for a PR
mti scan ./src --format markdown --output TENANT-ISOLATION-REPORT.md
# Upload SARIF to GitHub Code Scanning
mti scan ./src --format sarif --output results.sarif
信頼性とサプライチェーン
- npm Trusted Publishing — パッケージは長期間有効なトークンではなく、GitHub Actions OIDC を介して公開されます。公開のたびに、ワークフロー専用の短期間有効な認証情報が使用されます。
- プロベナンス証明 — 公開されたすべてのパッケージには、Sigstore の透明性ログに署名済みのプロベナンス情報が含まれます。パッケージがこのリポジトリ内の正確なソースからビルドされたことを検証できます。
- npm audit の脆弱性 0 件 — 依存関係は CI の実行ごとに監査されます。ロックファイルはコミットされており、再現可能なインストールのために CI では
npm ciを使用します。 - 決定論的なルール — 機械学習や確率的なスコアリングは使用しません。同じソースコードを与えると、スキャナーは常に同じ検出結果を返します。
- クロスプラットフォーム CI — Node 22 および 24 を使用して、Ubuntu、Windows、macOS でテストされています。Node 26 のカナリア実行は参考情報として実施されます。
- MIT ライセンス — 無料のオープンソースです。テレメトリ、外部への自動通信、データ収集はありません。
制限事項
静的解析には本質的な限界があります。ここでは、それらを率直に説明します。
- 関数内のフロー解析のみ。 スキャナーは、単一の関数本体内でデータフローを追跡します。関数呼び出し、ファイル、フレームワークのミドルウェア境界をまたぐフローは追跡しません。テナント分離の不備の多くは、シンクでガードが欠落している問題であり、関数間解析を必要としませんが、一部の特殊なケースは検出できない場合があります。
- 実行時の検証は行いません。 スキャナーはソースコードのパターンを検査します。データベースレベルの RLS ポリシーが実際に有効になっているか、ミドルウェアが実際に実行されるか、テナントコンテキストが実行時に実際に伝播されるかは検証できません。
- TypeScript と JavaScript のみ。 Python、Go、Ruby などの言語には、まだ対応していません。
- 誤検知が発生する可能性があります。 スキャナーは、誤検知を除外する仕組み(テストファイルの除外、認証シグナルの検出、信頼度スコアリング)を備えたパターンベースの検出を使用します。誤検知を減らすため、カスタム認証ヘルパーやテナントガードを
.mtirc.jsonで設定できます。 - MCP の stdio トランスポートのみ。 MCP サーバーは stdio を介してローカルで実行されます。v2.0 では、リモート/HTTP トランスポートに対応していません。
フロー解析の対象範囲について詳しくは、docs/FLOW-ANALYSIS-QUALIFICATION.md を参照してください。
技術スタック
- AST 解析:@babel/parser(TypeScript、JSX)、Prisma スキーマパーサー、SQL マイグレーションパーサー
- ルールエンジン:ガード検出と証拠構築を備えた RuleSpec 宣言型パターン
- CLI:Commander
- MCP:@modelcontextprotocol/server v2(stdio トランスポート、Zod スキーマ、構造化出力)
- 出力:ターミナル、JSON、SARIF 2.1.0、AI JSON、Markdown
- テスト:Vitest(203 件のテスト、Ubuntu、Windows、macOS でのクロスプラットフォーム CI)
ロードマップ
v2.0.0(現行)
- 57 個のルール(一般向け 42 個 + MCP 専用 15 個)
- TypeScript と JavaScript に対応
- Prisma スキーマ解析
- SQL マイグレーション解析(RLS、テナント列、インデックス)
- ターミナル、JSON、SARIF、AI JSON、Markdown 出力に対応した CLI
- MCP サーバー v2 SDK(stdio トランスポート、Zod スキーマ、構造化出力)
- 完全性、カバレッジ、懸念事項ファミリーを含む構造化 MCP 出力
- ルールパックのダイジェストと改ざん検出ハッシュを含むスキャンレシート
- 検証可能なスキャン成果物のためのエビデンスエンベロープ
- 行の移動に影響されない、安定した v2 セマンティックフィンガープリント
- OWASP MCP Top 10 へのマッピング(2025 年公式カテゴリ)
- パス境界の適用(トラバーサル、シンボリックリンク、UNC、Windows 8.3)
- 書き込みツールの制御(デフォルトは読み取り専用、抑制はオプトイン)
- 有効期限と承認者の記録を備えた抑制ポリシー
- 修正の証明状態を備えたベースライン追跡
- .mtirc.json での重大度の上書き
- 検証機能を備えたカスタムルールパック
- 設定可能な認証ヘルパーとテナントガード
- モデルスコープの分類と設定による上書き
- フレームワークの検出(Next.js、Express、Fastify)
- クロスプラットフォーム CI マトリックス(Node 22/24、Ubuntu/Windows/macOS)
今後の予定
- Python のサポート(FastAPI、Django、Flask)
- SQLAlchemy ORM の分析
- 監視モード(mti scan --watch)
- VS Code 拡張機能
- ランタイムの二者間テナント分離テストハーネス
- Go および Ruby の言語サポート
- AST キャッシュを使用した増分スキャン
リンク
- ランディングページ
- GitHub
- npm
- Docker Hub
- 変更履歴
- コントリビューション
- セキュリティポリシー
- HAIEC(Human AI Evidence Company)— AI セキュリティの検証と監査証拠のプラットフォーム
- Subodh Kc — 開発者
ライセンス
MIT。無料のオープンソースです。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。