
こんにちは。よっしーです(^^)
背景
この連載では、Claude Codeの公式ドキュメントを1ページずつ読み解いていきます。公式ドキュメントは情報が網羅されている分、「結局どの機能を、どんな場面で使えばいいのか」は自分で考える必要があり、読むのに意外と時間がかかります。そこで、私が実務で使うために読み込んだ内容を「使う場面→実例コード」の順に整理して残していくことにしました。専門家の解説というより、一次情報を読んだ記録です。推測や動作を確認していない部分には、その都度そう書きます。
1. これは一言でいうと何か
権限ルールは、Claude Code がアクセスして実行できる内容を、ツール単位・コマンド単位・パス単位で指定する仕組みです。バージョン管理にチェックインして組織全体に配布でき、開発者が個別にカスタマイズすることもできます。
前回(第15回)の権限モードが「確認の頻度」を決めるベースラインだったのに対し、今回はその上に重ねる個別のルールです。押さえるべき前提が1つあります。権限ルールを実装しているのは Claude Code であって、モデルではありません。 プロンプトや CLAUDE.md の指示は Claude が何をしようとするかを形作りますが、Claude Code が許可する内容は変わりません。
2. どういう場面で役立つか
ルールは3種類です。Allow(手動承認なしで使える)、Ask(使おうとするたびに確認)、Deny(使用を防止)。/permissions で一覧と、それがどの settings.json 由来かを確認できます。
- テストとビルドだけ通したい:
Bash(npm run *)を allow に置けば、日常的なコマンドの確認が消えます。 - push だけは必ず止めたい:
Bash(git push *)を deny に置きます。 - 秘密ファイルを読ませたくない:
Read(.env)のような deny ルールを書きます。 - 特定のサブエージェントを無効化したい:
Agent(Explore)を deny に置きます。
効かない書き方・向かない使い方。
- deny ルールに例外は作れません。 評価は deny → ask → allow の順で、最初にマッチしたものが結果を決め、ルールの具体性は順序を変えません。
Bash(aws *)を deny にすると、より狭いBash(aws s3 ls)の allow があってもブロックされます。ask と allow の間も同じで、マッチする ask ルールがあれば、より具体的な allow があってもプロンプトが出ます。 - コマンド引数を制約する Bash パターンは脆弱です。 ドキュメントは
Bash(curl http://github.com/ *)を例に、オプションの前置き、プロトコル違い、リダイレクト、変数展開、余分なスペースで容易に外れると説明しています。URL を絞りたいならcurlやwgetを deny にしてWebFetch(domain:...)を使うか、PreToolUse フックで検証してください。WebFetch だけを使ってもネットワークアクセスは防げません。Bash が許可されていれば任意の URL に到達できます。 - Read / Edit の deny は万能ではありません。 Claude の組み込みファイルツールと、
cat・sedなど Claude Code が認識する Bash のファイルコマンドには効きますが、Python や Node のスクリプトがファイルを自分で開く場合には適用されません。OS レベルで止めたいならサンドボックスを使います。
3. コード・コマンドの実例と解説
前提条件
- ルールの形式は
ToolまたはTool(specifier)です。括弧なしのツール名は全使用にマッチします(Bash(*)はBashと同等)。 - deny ルールは書き方で挙動が変わります。
Bashのようなベアツール名はツールを Claude のコンテキストから完全に削除するため、Claude はその存在すら見ません。Bash(rm *)のようなスコープ付きルールはツールを残したまま、該当する呼び出しだけをブロックします。 - 権限プロンプトで
Ctrl+Eを押すと、コマンドの説明(何をするか、なぜ実行しようとするか、何が問題になり得るか)が低・中・高のリスクラベル付きで表示されます。表示してもコマンドは実行されません。
ワイルドカードで許可・拒否する
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)",
"Bash(git * main)",
"Bash(* --version)",
"Bash(* --help *)"
],
"deny": [
"Bash(git push *)"
]
}
}
npm と git commit を許可し、git push をブロックする設定です。ワイルドカードはコマンド内の任意の位置に置け、単一の * はスペースを含む任意の文字列にマッチします(Bash(git * main) は git push origin main にも git merge main にもマッチ)。
* の前のスペースが決定的に重要です。 Bash(ls *) は単語境界を強制するため ls -la にマッチしますが lsof にはマッチしません。スペースなしの Bash(ls*) は両方にマッチします。:* サフィックスは末尾のワイルドカードと同等(Bash(ls:*) = Bash(ls *))ですが、末尾でのみ認識されます。Bash(git:* push) のコロンはリテラル文字として扱われ、git コマンドにはマッチしません。
複合コマンドは分割して評価される
Claude Code はシェルオペレータを認識するため、Bash(safe-cmd *) があっても safe-cmd && other-cmd は実行できません。区切りとして認識されるのは &&、||、;、|、|&、&、改行で、各サブコマンドが独立してマッチする必要があります。
「はい、今後は聞かない」で複合コマンドを承認した場合も、複合文字列そのままではなくサブコマンドごとに個別ルールが保存されます(1つの複合コマンドで最大5つ)。
パスの書き方はアンカーで決まる
Read と Edit のルールは gitignore 仕様に従い、4種類のパターンがあります。
| パターン | 意味 | 例 |
|---|---|---|
//path | ファイルシステムルートからの絶対パス | Read(//Users/alice/secrets/**) |
~/path | ホームディレクトリからのパス | Read(~/Documents/*.pdf) |
/path | 設定ソースからの相対パス | Edit(/src/**/*.ts) |
path または ./path | 現在のディレクトリからの相対パス | Read(*.env) |
最も間違えやすいのは3行目です。 /Users/alice/file は絶対パスではありません。単一の先頭スラッシュは設定ソースにアンカーされます。ユーザー設定に Read(/secrets/**) と書くと、プロジェクト内の secrets ではなく ~/.claude/secrets/** をブロックすることになります。全プロジェクトに効かせたいなら // か ~/ を使ってください。
なお、ベアファイル名は gitignore セマンティクスで任意の深さにマッチするため、Read(.env) と Read(**/.env) は同等です。ただしこれは現在のディレクトリ以下だけで、親や別プロジェクトの .env はブロックしません。それも止めたいなら Read(//**/.env) です。
MCP ツールをまとめて拒否する
{
"permissions": {
"deny": [
"mcp__*"
]
}
}
deny と ask はツール名の位置でもグロブを受け付けます。mcp__* は全サーバーの全 MCP ツールにマッチします。ただし allow 側は対称ではありません。 許可ルールはリテラルの mcp__<server>__ プレフィックスの後でしかグロブを受け付けず、"*" や "mcp__*" のようなアンカーなしの許可グロブは警告とともにスキップされ、自動承認されません。
サブエージェントを無効化する
{
"permissions": {
"deny": ["Agent(Explore)"]
}
}
Agent(AgentName) で個別のサブエージェントを制御します。--disallowedTools CLI フラグでも同じことができます。
その他(PowerShell ルールとエイリアス正規化、入力パラメータマッチ Tool(param:value)、プロセスラッパーの扱いと devbox run などの落とし穴、読み取り専用コマンドの組み込みセット、WebFetch のワイルドカード境界、シンボリックリンクの扱い、Cd ルール、additionalDirectories と --add-dir で読み込まれる設定の一覧、管理のみの設定18項目、ワークスペーストラストの詳細)は公式ドキュメントを参照してください。
4. まとめと次回予告
- ルールは deny → ask → allow の順で評価され、最初のマッチが勝ちます。具体性では覆せません。
- Bash は
*の前のスペースで挙動が変わり、複合コマンドはサブコマンドごとに判定されます。 - パスは4つのアンカーを持ちます。
/pathは「設定ソースからの相対」であって絶対パスではありません。
優先順位は「拒否が常に勝つ」で貫かれています。 設定の優先順位は 管理設定 > コマンドライン引数 > ローカルプロジェクト > 共有プロジェクト > ユーザー設定 ですが、どのレベルであれ拒否されたツールを他のレベルが許可することはできません。管理設定の deny は --allowedTools で上書きできず、ユーザー設定の deny はプロジェクト設定の allow をブロックします。
フックとの関係も同じ形です。 PreToolUse フックは権限プロンプトの前に実行されますが、フックの決定が権限ルールをバイパスすることはありません。deny ルールと ask ルールはフックの戻り値に関係なく評価されます。一方でブロッキングフックは allow ルールより優先され、終了コード2で終わるフックは権限ルール評価前に呼び出しを止めます。「Bash は全部許可して、一部だけフックで止める」という構成が成立するのはこのためです。
最後に、チーム配布で引っかかりやすい点を1つ。プロジェクトの .claude/settings.json にある permissions.allow と additionalDirectories は、ワークスペーストラストダイアログを受け入れるまで適用されません。 読み込まれてはいるが効いていない状態です。これらは「機能を付与する」ルールだからで、制限のみを行う deny と ask は影響を受けません。トラストダイアログには、そのフォルダが付与する許可ルールと追加ディレクトリが表示されるので、受け入れる前に確認できます。
次回予告:Bash コマンドを OS レベルで隔離する「サンドボックス」を取り上げる予定です。
関連ページ(本記事で触れた概念の詳細):モードの選び方 →「権限モードを選択する」、完全な設定リファレンス →「設定」、OS レベルの隔離 →「サンドボックス」、分類器への信頼インフラ登録 →「auto モードを設定する」、PreToolUse の書き方 →「Hooks」、ツールの正規名 →「ツール参照」、ワークスペーストラスト →「セキュリティ」。
本記事は執筆時点の公式ドキュメント(権限を設定する)に基づきます。最新は公式ドキュメントをご確認ください。

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)

コメント