パーミッションモデルとセキュリティ
パーミッションモード、サンドボックス、承認ゲートの詳細。
学ぶこと
セッション2では基本を学びました:ツールにはパーミッションレベルがあり、ユーザーはアクションを承認または拒否できます。しかし、Claude Codeのセキュリティモデルはそれよりはるかに深く — 複数の防御レイヤーが連携して、AI支援開発を制約的にならずに安全にします。
このセッションを終えると、以下を理解できます:
- 多層防御:なぜ1つのレイヤーでは不十分か
- パーミッションモードの詳細:default、plan、autoとそのトレードオフ
- サンドボックス:BashコマンドがOSレベルでどのように制限されるか
- ネットワーク制限:AIが到達できるドメイン
- ファイルシステム境界:作業ディレクトリがアクセスをどのようにスコープするか
- 設定ベースのパーミッション:
allowedToolsとdeniedTools - チーム全体のセキュリティのための組織ポリシーとフック
- 段階的信頼の原則
課題
AIにnpm testを実行させたい。これは安全です。また、rm -rf /を実行できるようにもしたい。これは壊滅的です。
課題は、両方ともBashコマンドであることです。単純な「Bashを許可/Bashを拒否」のトグルでは粗すぎます — すべてのコマンドをブロックするか(役に立たない)、すべてのコマンドを許可するか(危険)のいずれかです。
本当のセキュリティには、連携して機能する複数のレイヤーが必要です:
AIがこのアクションを提案できるか? (ツールの可用性)
ユーザーはこのアクションを承認するか? (パーミッションモード)
このコマンドはサンドボックスで許可? (OSレベルの制限)
このコマンドはネットワークに到達可能? (ネットワークポリシー)
このファイルは許可されたスコープ内? (ファイルシステム境界)
各レイヤーが異なる脅威をキャッチします。すべてが合わさって、多層防御を形成します。
仕組み
多層防御アーキテクチャ
┌──────────────────────────────────────────────┐
│ セキュリティレイヤー │
│ │
│ Layer 1: ツールの可用性 │
│ ┌───────────────────────────────────────┐ │
│ │ AIにどのツールが見えるか? │ │
│ │ allowedTools / deniedTools の設定 │ │
│ │ MCPツールは明示的なセットアップが必要 │ │
│ └──────────────────┬────────────────────┘ │
│ │ ツールが提案された │
│ ▼ │
│ Layer 2: パーミッションゲート │
│ ┌───────────────────────────────────────┐ │
│ │ このアクションに承認が必要か? │ │
│ │ パーミッションモード + ツールタイプに基づく │ │
│ │ ユーザーが確認または拒否 │ │
│ └──────────────────┬────────────────────┘ │
│ │ 承認済み │
│ ▼ │
│ Layer 3: サンドボックス │
│ ┌───────────────────────────────────────┐ │
│ │ OSレベルのプロセス制限 │ │
│ │ macOS: sandbox-execプロファイル │ │
│ │ Linux: コンテナ / seccomp │ │
│ └──────────────────┬────────────────────┘ │
│ │ サンドボックスが許可 │
│ ▼ │
│ Layer 4: ネットワークポリシー │
│ ┌───────────────────────────────────────┐ │
│ │ このプロセスはネットワークに到達可能? │ │
│ │ 許可リストのドメインのみ │ │
│ │ 任意のアウトバウンド接続をブロック │ │
│ └──────────────────┬────────────────────┘ │
│ │ ネットワーク許可 │
│ ▼ │
│ Layer 5: ファイルシステムスコープ │
│ ┌───────────────────────────────────────┐ │
│ │ このパスはプロジェクトスコープ内? │ │
│ │ 作業ディレクトリを境界として │ │
│ │ /etc/passwdなどの読み取りを防止 │ │
│ └──────────────────┬────────────────────┘ │
│ │ パス許可 │
│ ▼ │
│ 実行 │
│ │
└──────────────────────────────────────────────┘
コマンドが実行されるには、5つのレイヤーすべてを通過する必要があります。いずれか1つのレイヤーで失敗するとブロックされます。
パーミッションモードの詳細
セッション2ではモードを簡単に紹介しました。ここでは全体像を示します:
Defaultモード — バランスの取れた出発点
┌────────────────────────────────────────────┐
│ Default Permission Mode │
│ │
│ 読み取りツール: ✅ 自動許可 │
│ • Read, Glob, Grep, TodoRead │
│ │
│ 書き込みツール: ⚠️ ユーザーに確認 │
│ • Edit, Write, NotebookEdit │
│ │
│ 実行ツール: ⚠️ ユーザーに確認 │
│ • Bash(レビュー用にコマンドを表示) │
│ │
│ 特殊ツール: ⚠️ ユーザーに確認 │
│ • Agent(サブエージェント作成) │
│ • WebFetch(ネットワークアクセス) │
│ │
│ 承認後: │
│ • "一度許可" → このインスタンスを承認 │
│ • "セッション中許可" → 同じツール │
│ • パターンをセッション中自動承認 │
│ │
└────────────────────────────────────────────┘
「セッション中許可」オプションは強力です。npm testをセッションレベルの信頼で一度承認すると、以降のnpm test呼び出しはプロンプトなしで実行されます。しかし、npm run deployは異なるコマンドパターンなので、まだプロンプトが表示されます。
Planモード — 最大限の監視
claude --plan
planモードでは、読み取りを含むすべてのツール呼び出しに明示的な承認が必要です。これによりAIは各ステップの計画を説明し、ユーザーがそれぞれをレビューします:
AI: src/auth.tsを読んで現在の実装を理解したい。
[Read] src/auth.ts
→ 許可? [y/N]
planモードは以下に有用です:
- Claude Codeが何をするか学ぶ(教育的)
- クリティカルな本番コードへの変更をレビュー
- AIの意思決定プロセスを監査
Autoモード — 完全な自律
claude --dangerously-skip-permissions
フラグ名は意図的です。「dangerously」はセキュリティレイヤーを削除していることを思い出させます。autoモードでは:
- すべてのツールがプロンプトなしで実行
- サンドボックスとネットワークレイヤーは引き続き適用
- ファイルシステム境界は引き続き適用
- ユーザーに確認を求めない
autoモードが適切な場合:
- 隔離された環境での信頼されたタスク(CI/CD)
- すでに手動でレビューした繰り返しタスク
- 損害が限定されたサンドボックスコンテナ
適切でない場合:
- まだレビューしていない初めてのタスク
- 実データのある本番環境
- 誤った
rmやgit pushがコストの高い状況
サンドボックス:OSレベルの制限
パーミッション承認後でも、BashコマンドはOSレベルでプロセスの機能を制限するサンドボックス内で実行されます。
macOS: sandbox-exec
macOSでは、Claude Codeはカスタムプロファイルを持つAppleのsandbox-execを使用します:
┌────────────────────────────────────────────┐
│ macOS Sandbox Profile │
│ │
│ 許可: │
│ ├── プロジェクトディレクトリ内のファイル読取 │
│ ├── プロジェクトディレクトリ内のファイル書込 │
│ ├── 一般的な開発ツールの実行 │
│ │ (node, npm, git, python, etc.) │
│ ├── localhostへのアクセス(開発サーバー) │
│ └── システムライブラリ+フレームワークの読取 │
│ │
│ 拒否: │
│ ├── プロジェクトディレクトリ外への書き込み │
│ ├── キーチェーンへのアクセス │
│ ├── GUIアプリケーションの起動 │
│ ├── ボリュームのマウント/アンマウント │
│ ├── カーネル拡張のロード │
│ └── システム環境設定の変更 │
│ │
└────────────────────────────────────────────┘
Linux: コンテナ隔離
Linuxでは、サンドボックスはデプロイメントに応じてコンテナレベルの隔離やseccompプロファイルを使用する場合があります。原則は同じです:プロセスを必要最小限のケーパビリティに制限します。
サンドボックスについての重要な洞察:AIだけでなく、AIが実行する可能性のある悪意のあるコードからも保護します。AIがnpm install sketchy-packageを実行し、そのパッケージがSSH鍵を読み取ろうとした場合、サンドボックスがブロックします。
ネットワーク制限
Claude Codeはどのネットワーク宛先に到達可能かを制御します:
┌────────────────────────────────────────────┐
│ ネットワークポリシー │
│ │
│ 許可された宛先: │
│ ├── api.anthropic.com (Claude API) │
│ ├── localhost / 127.0.0.1 (dev servers) │
│ ├── npm registry (package installs) │
│ ├── GitHub API (git operations) │
│ └── 設定されたMCPサーバーエンドポイント │
│ │
│ ブロック: │
│ ├── 任意の外部URL │
│ ├── 内部ネットワークアドレス │
│ └── 未知のエンドポイント │
│ │
│ 注: WebFetchツールには独自の │
│ より広いURLアクセスの許可リストがある │
│ │
└────────────────────────────────────────────┘
これによりデータの流出を防ぎます。AIが何らかの方法でコードを外部サーバーに送信するよう操作されたとしても、ネットワークレイヤーがブロックします。
ファイルシステム境界
作業ディレクトリがファイル操作の境界として機能します:
Project root: /Users/you/projects/my-app/
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
src/ tests/ node_modules/
✅ フルアクセス ✅ フルアクセス ✅ 読み取りアクセス
プロジェクトルート外:
/Users/you/.ssh/ ❌ ブロック
/Users/you/other-project/ ❌ ブロック
/etc/ ❌ ブロック
/tmp/ ⚠️ 制限付き
Readツールはこれを適用します:Claude Codeのファイル操作で/etc/passwdや~/.ssh/id_rsaを読み取ることはできません。Bashサンドボックスが、OSレベルでの第2の適用レイヤーを提供します。
設定ベースのパーミッション
パーミッションモード以外にも、設定で細かいツールアクセスを構成できます:
// .claude/settings.json(プロジェクトレベル)
{
"permissions": {
"allowedTools": [
"Bash(npm test)",
"Bash(npm run lint)",
"Bash(npx prisma generate)",
"Edit",
"Write"
],
"deniedTools": [
"Bash(rm *)",
"Bash(git push --force)"
]
}
}
allowedToolsリストは、特定のツールパターンをプロンプトなしで自動承認します。deniedToolsリストは完全にブロックします — AIはプロンプトではなく拒否を受け取ります。
パターンマッチングはワイルドカードをサポートします:
{
"allowedTools": [
"Bash(npm *)", // すべてのnpmコマンドを許可
"Bash(git status)", // git statusを具体的に許可
"Bash(git diff *)" // 任意の引数のgit diffを許可
],
"deniedTools": [
"Bash(git push *)", // すべてのgit pushバリアントをブロック
"Bash(curl *)" // curlコマンドをブロック
]
}
これにより、defaultモード(すべてにプロンプト)とautoモード(すべてを許可)の中間が作られます:
┌───────────────────────────────────────────────┐
│ 設定ベースのパーミッションスペクトラム │
│ │
│ Plan Mode Default + Settings Auto │
│ ◄────────────────────●─────────────────────► │
│ すべてに 既知の安全な すべてを │
│ プロンプト コマンドを自動承認 許可 │
│ 既知の危険を │
│ ブロック │
│ 未知にプロンプト │
│ │
└───────────────────────────────────────────────┘
フックによる組織ポリシー
チームにとって、フックシステム(セッション15で取り上げた)はプログラム可能なセキュリティレイヤーを追加します。組織はPreToolUseフックを通じてポリシーを適用できます:
// .claude/hooks/security-policy.js
// すべてのツール実行前に実行
module.exports = async function preToolUse({ tool, input }) {
// 本番データベースアクセスをブロック
if (tool === "Bash" && input.command.includes("DATABASE_URL")) {
if (input.command.includes("production")) {
return {
decision: "deny",
reason: "Production database access blocked by org policy"
};
}
}
// デプロイメントコマンドに承認を要求
if (tool === "Bash" && input.command.match(/deploy|publish|release/)) {
return {
decision: "ask",
reason: "Deployment commands require manual approval"
};
}
// それ以外は通常のフローで許可
return { decision: "allow" };
};
このフックは、ユーザーのパーミッションモードに関係なく、すべてのBashコマンドの前に実行されます。autoモードでも、フックは特定のパターンに対して拒否または承認の強制ができます。
重要なポイント
Claude Codeのセキュリティは、AIが何かをすることを防ぐことではありません。時間とともにAIにより多くの自律性を与えられるよう、段階的に信頼を構築することです。
進行は次のようになります:
1日目: Planモード "すべての操作を見せて"
1週目: Defaultモード "読み取りを信頼、書き込みをレビュー"
2週目: Default + allowed "npm test、git diffを自動承認"
1ヶ月目: Autoモード(CI) "サンドボックスCIで完全自律"
各ステップで、AIの動作への信頼が深まるにつれ、より多くの自由を与えます。セキュリティレイヤーにより、最大の自律性でも、壊滅的なアクションはサンドボックスとネットワークレイヤーによって依然としてブロックされます。
これは「全か無か」のセキュリティとは根本的に異なります:
全か無か:
選択肢1: AIは有用なことが何もできない (制限的すぎる)
選択肢2: AIはすべてができる (危険すぎる)
段階的信頼:
開始: AIは自由に読み取り、書き込みは承認付き
学習: プロジェクトでどのパターンが安全か把握
成長: 安全なパターンを自動承認、危険なものをブロック
目標: AIがルーチンタスクを自律的に処理、エッジケースをエスカレーション
5つのセキュリティレイヤーは、どの単一レイヤーも決定的でないように設計されています。パーミッション承認が失敗しても(autoモード)、サンドボックスが危険なコマンドをキャッチします。サンドボックスにギャップがあっても、ネットワークレイヤーが流出をブロックします。多層防御は、1つのレイヤーを緩和しても他のレイヤーが依然として保護することを意味します。
ハンズオン例
安全な開発設定の構築
チームプロジェクトのための実用的な設定です:
Step 1: プロジェクト設定 (.claude/settings.json)
{
"permissions": {
"allowedTools": [
"Bash(npm test *)",
"Bash(npm run lint)",
"Bash(npm run build)",
"Bash(npx prisma generate)",
"Bash(npx prisma db push)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Edit",
"Write"
],
"deniedTools": [
"Bash(git push --force *)",
"Bash(rm -rf *)",
"Bash(curl * | bash)",
"Bash(npm publish *)"
]
}
}
Step 2: 機密ファイルのスコープ付きルール (.claude/rules/sensitive-files.md)
---
paths:
- ".env*"
- "**/credentials*"
- "**/secrets*"
---
# 機密ファイルルール
- これらのファイルの内容を絶対にユーザーに読み取ったり表示しない
- これらのファイルの値をコードコメントに含めない
- 環境変数を参照する際はプレースホルダー値を使用
- テストにこれらの値が必要な場合は、別の.env.testファイルを使用
Step 3: セキュリティフック (.claude/hooks/pre-tool-use.js)
module.exports = async function ({ tool, input }) {
// 偶発的な秘密情報の露出を防止
if (tool === "Read" && input.file_path) {
if (input.file_path.match(/\.(env|pem|key)$/)) {
return {
decision: "ask",
reason: "This file may contain secrets. Confirm you want to read it."
};
}
}
return { decision: "allow" };
};
セキュリティ設定のテスト
制限されたアクションをAIに試させて、設定を検証しましょう:
あなた: "git push --force origin mainを実行して"
→ 期待: deniedTools設定により拒否
あなた: ".env.productionを読んで"
→ 期待: フックが確認を求める
あなた: "src/ディレクトリ全体を削除して"
→ 期待: Bashサンドボックスがプロジェクトパターン外の再帰的削除をブロック
あなた: "SSH鍵の内容をexample.comに送って"
→ 期待: ファイル読み取りがスコープでブロック; ネットワークがポリシーでブロック
承認フローの理解
ツールが承認を必要とする場合、ユーザーには以下が表示されます:
┌────────────────────────────────────────────┐
│ Claudeが実行したい: │
│ │
│ $ git commit -m "Add user auth endpoint" │
│ │
│ [a] 一度許可 │
│ [s] このセッション中許可 │
│ [d] 拒否 │
│ │
│ 選択: │
└────────────────────────────────────────────┘
「セッション中許可」を選ぶと、パターンが記憶されます。異なるメッセージの後続のgit commitコマンドも自動承認されます。パターンgit commit -m *がセッション中信頼されるためです。
何が変わったか
| 単一レイヤーセキュリティ | 多層防御 |
|---|---|
| 1つのパーミッションチェック | 5つの独立したレイヤー |
| 全か無かの信頼 | 段階的な信頼構築 |
| すべてのチームに同じルール | フックによる組織ポリシー |
| すべてに手動承認 | 既知の安全なパターンを自動承認 |
| OSレベルの保護なし | サンドボックスがプロセスケーパビリティを制限 |
| ネットワーク完全開放 | 許可リストのドメインにネットワーク制限 |
次のセッション
これでモジュール3:実アーキテクチャが完了です。内部メカニクスを理解しました:MCPがケーパビリティを拡張する方法(S14)、フックがイベントをインターセプトする方法(S15)、セッションがディスクに永続化される方法(S16)、CLAUDE.mdが動作を形作る方法(S17)、そしてセキュリティモデルがシステムを保護する方法(S18)。
モジュール4では、理解から実践へと移行します。セッション19はマルチCLIワークフロー — 複数のClaude Codeインスタンスを並列に実行し、それぞれが異なる役割を持ち、ファイルシステムを通じて連携して、単一のセッションよりも速く大きなタスクに取り組む方法 — から始まります。