Claude Code / MCP を安全に使うための実践ガイド — settings.json の多層防御と deny の落とし穴

セキュリティ研究者のyousukezan氏(バグバウンティプログラムでランク1位受賞歴あり)が紹介した Zenn 記事「Claude Code / MCP を安全に使うための実践ガイド」が注目を集めています。165いいね、161ブックマークという反響は、Claude Code のセキュリティ設定に対する実務者の強い関心を示しています。

本記事では元記事の内容を掘り下げつつ、公式ドキュメントや GitHub Issues の情報を加えて、実務で本当に機能するセキュリティ設定を整理します。

背景 — 8桁後半の被害事例

この記事が書かれた背景には、AI コーディングツール経由で Google Ads の MCC が乗っ取られ、8桁後半の被害が発生した事例があります。報告された4つの攻撃ベクターは全て Claude Code / MCP の利用シーンで再現可能です。

攻撃ベクターClaude Code での該当リスク
間接プロンプトインジェクションWebページに埋め込まれた隠し指示をAIが実行
プロンプトサプライチェーン攻撃外部から取得した CLAUDE.md / settings.json / .mcp.json の改ざん
MCP権限悪用(Tool Poisoning)許可済みMCPツールの悪意ある利用
クレデンシャルリークトークンやAPIキーのログ・git履歴への残存

最も重要な3つの設定

元記事が推奨する最小限の設定は3つです。

1. bypassPermissions モードの無効化

1
2
3
4
5
{
  "permissions": {
    "disableBypassPermissionsMode": "disable"
  }
}

--dangerously-skip-permissions フラグは全ての承認プロンプトをスキップします。公式ドキュメントによると、このモードではClaude がファイルの削除、破壊的なコマンドの実行、不可逆な変更を承認なしで行えます。disableBypassPermissionsMode: "disable"組織全体でこのモードを禁止できます。

エンタープライズ環境では managed-settings.json に設定することで、ユーザーが上書きできないポリシーレベルの強制が可能です。

2. プロジェクトMCPサーバーの自動承認を無効化

1
2
3
{
  "enableAllProjectMcpServers": false
}

この設定が true の場合、プロジェクト内の .mcp.json で定義された全てのMCPサーバーが自動的に有効になります。悪意あるリポジトリを clone しただけでMCPサーバーが起動するリスクがあり、これは過去の CVE-2025-59536(CVSS 8.7)で実際に悪用されました。

3. HTTP通信可能なランタイムの制限

1
2
3
4
5
6
7
8
{
  "permissions": {
    "allow": [
      "Bash(git status)",
      "Bash(npm run *)"
    ]
  }
}

Bash(python3 *)Bash(node *) を allow リストに入れると、これらのランタイムを経由してHTTP通信が可能になります。つまりネットワークアクセス制御のバイパスが成立します。allow リストには必要最小限のコマンドのみを個別に指定すべきです。

deny 設定の重大な落とし穴

ここからが元記事では十分に触れられていない、しかし実務上最も重要な問題です。

deny ルールが機能しないバグ

GitHub Issue #6699 で報告されているように、settings.json の deny ルールは複数のバージョンで正しく機能していません

Issue内容状態
#6699deny permissions が全く強制されない報告済み
#6631Read/Write ツールで deny が無視される報告済み
#12918v2.0.56 で Edit/Write の deny が無効報告済み
#24846.env ファイルの Read deny が強制されない報告済み
#13785deny 設定があっても CLAUDE.md が上書きされる報告済み
#11226Hooks 自体が Edit/Write で改変可能報告済み

つまり、settings.json に以下のように書いても:

1
2
3
4
5
6
7
8
9
{
  "permissions": {
    "deny": [
      "Read(.env)",
      "Read(**/*.pem)",
      "Write(.env)"
    ]
  }
}

Claude Code は .env ファイルを読み取れてしまう可能性があります。

唯一の信頼できる防御: PreToolUse Hooks

deny ルールの代替として、PreToolUse Hooks が推奨されています。Hooks はツール呼び出しの前に実行され、非ゼロの終了コードでツール実行を拒否できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read|Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "python3 /path/to/deny_sensitive_files.py"
          }
        ]
      }
    ]
  }
}

Hook スクリプトの例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python3
import sys, json, re

SENSITIVE_PATTERNS = [
    r'\.env',
    r'\.pem$',
    r'credentials',
    r'\.ssh/',
    r'keystore',
]

def check_path(tool_input):
    path = tool_input.get('file_path', '') or tool_input.get('path', '')
    for pattern in SENSITIVE_PATTERNS:
        if re.search(pattern, path, re.IGNORECASE):
            print(f"BLOCKED: Access to sensitive file matching '{pattern}'", file=sys.stderr)
            sys.exit(2)

if __name__ == '__main__':
    tool_input = json.loads(sys.stdin.read())
    check_path(tool_input)

ただし、Issue #11226 で指摘されているように、Hook 自体が Edit/Write ツールで改変される可能性があります。Hook ファイルは読み取り専用パーミッション(chmod 444)に設定し、プロジェクトディレクトリ外に配置することが推奨されます。

MCP Tool Poisoning — 見えない脅威

MCP のセキュリティで最も深刻な問題は Tool Poisoning です。Invariant Labs の報告によると、悪意ある指示がツールのメタデータ(description フィールド等)に埋め込まれ、人間には見えないがAIモデルには読み取れる状態で攻撃が成立します。

Tool Poisoning の仕組み

1. 悪意あるMCPサーバーがツールを登録
2. ツールの description に隠し指示を埋め込む
   (ユーザーには表示されない部分)
3. AIモデルがツールを呼び出す際に隠し指示を読み取る
4. 機密データの窃取や不正操作が実行される

Palo Alto Networks Unit 42 は、MCP Sampling を経由した新しいプロンプトインジェクション攻撃ベクターも報告しています。

Rug Pull 攻撃

さらに危険なのは Rug Pull です。ツールの description や動作がユーザーの承認後に無断で変更される攻撃です。最初は正常に動作するツールとして信頼を獲得し、後から悪意ある動作に切り替わります。MCP Manager の分析によると、バージョン固定(version pinning)がこの攻撃に対する主要な防御策です。

MCP セキュリティ対策

対策説明
バージョン固定MCPサーバーのバージョンをピン留めし、無断更新を防止
ツール説明の可視化AIに見える部分と人間に見える部分を区別して表示
最小権限各ツールに必要最小限の権限のみを付与
入力バリデーションツールメタデータを含む全入力に対するサニタイズ
MCPゲートウェイランタイムでの傍受・サニタイズが唯一の信頼できる防御

実践的な多層防御の構成

settings.json の deny だけに頼れない現状を踏まえ、実務で推奨される多層防御を整理します。

レイヤー1: settings.json(基本設定)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "permissions": {
    "disableBypassPermissionsMode": "disable",
    "allow": [
      "Bash(git status)",
      "Bash(git diff *)",
      "Bash(git log *)",
      "Bash(npm run build)",
      "Bash(npm run test)"
    ],
    "deny": [
      "Read(.env*)",
      "Read(**/*.pem)",
      "Read(**/*.key)",
      "Bash(curl *)",
      "Bash(wget *)",
      "Bash(python3 -c *)",
      "Bash(node -e *)"
    ]
  },
  "enableAllProjectMcpServers": false
}

deny は現在バグがあるため期待通りに動作しない可能性があることを認識した上で、防御の1層目として設定します。

レイヤー2: PreToolUse Hooks(実効的な防御)

deny の代替として、Hooks で機密ファイルへのアクセスをブロックします。Hook ファイルは chmod 444 に設定し、プロジェクトディレクトリ外(例: ~/.claude/hooks/)に配置します。

レイヤー3: CLAUDE.md(運用ルール)

1
2
3
4
5
## セキュリティルール
- .env ファイルの内容を読み取らない
- APIキー、トークン、パスワードをコードに埋め込まない
- 外部URLへのデータ送信を行わない
- MCP サーバーの追加は人間の承認を必須とする

ただし CLAUDE.md はプロンプトインジェクション対策としては脆弱です。AIへの「お願い」であり、技術的な強制力はありません。

レイヤー4: サンドボックス(高リスク作業時)

/sandbox

依存パッケージの更新やuntrustedリポジトリの調査時に有効化します。公式ドキュメントによると、サンドボックスはOS レベルのメカニズム(Linux: bubblewrap、macOS: seatbelt)でBash実行をプロジェクトディレクトリに制限し、ネットワークアクセスを承認済みドメインに限定します。

レイヤー5: 環境分離(根本対策)

最も確実な防御は、機密情報をClaude Code の到達範囲外に置くことです。

  • APIキーは環境変数ではなく aws-vault や macOS Keychain で管理する
  • .env ファイルは Claude Code を起動するディレクトリに置かない
  • 広告アカウントやクラウドコンソールの認証情報は別マシン・別ブラウザプロファイルで管理する

まとめ

  • 3つの必須設定: disableBypassPermissionsMode: "disable"enableAllProjectMcpServers: false、allow リストの最小化が最低限の防御
  • deny ルールは信頼できない: GitHub Issues で複数バージョンにわたり deny が機能しないバグが報告されている。deny だけに頼ってはいけない
  • PreToolUse Hooks が実効的な防御: deny の代替として Hooks でツール呼び出しを検査・拒否する。ただし Hook 自体の改変リスクにも注意
  • MCP Tool Poisoning は深刻な脅威: ツールの description に隠し指示を埋め込む攻撃。バージョン固定とMCPゲートウェイが防御の鍵
  • 多層防御が必須: settings.json + Hooks + CLAUDE.md + サンドボックス + 環境分離の5層で守る。単一の対策に依存しない
  • 最も確実な対策は環境分離: 機密情報を Claude Code の到達範囲外に置くことが根本的な解決策

参考