【Claude Code実践入門 第6回】allow・ask・denyのルールと設定ファイル ― 書き方と評価の順番、前方一致の落とし穴とdenyの限界、設定ファイルの階層、Ansibleの設定例

生成AI
スポンサーリンク
スポンサーリンク

「許可のルールを書いたのに、思ったとおりには確認なしで動きません」
「.env を deny に書いたので、もう読まれないはずですよね?」

第5回(権限モードとauto mode)で、権限モードは確認なしで実行する範囲の基準を決めるものだと見ました。モードの上に重ねて、特定の操作を事前に許可したり、確認させたり、止めたりするのが権限ルール(allow・ask・deny)です。

ただし、ルールには癖があります。評価の順番、前方一致、つないだコマンドの扱い、そして deny が「境界」ではないこと。知らないと、「書いたのに効かない」「書いたつもりで守れていない」のどちらも起きます。

第6回では、ルールの書き方と評価の順番、前方一致の落とし穴と deny の限界、設定ファイルの階層、Ansible の作業での設定例を扱います。数値・仕様は2026年10月時点です。


allow・ask・denyルールの書き方

ルールは、設定ファイルの permissions に allow・ask・deny の3つのリストとして書きます。

  • 形式:ツール名 または ツール名(条件)。例:Bash(git diff *)、Read(./.env)、WebFetch(domain:docs.ansible.com)
  • 評価の順番:deny → ask → allow の順に調べ、最初に一致したものが決める。より具体的なルールが優先されるわけではない
  • その結果①:広い deny に、狭い allow で例外を作ることはできない
  • その結果②:広い ask があると、それに一致するものは、狭い allow があっても確認される。ask に一致したものは、使うたびに確認が出る
  • * の意味:空白を含む任意の文字列に一致する。Bash(ls:*) と Bash(ls *) は同じ意味
  • つないだコマンド:&&・;・| でつないだものは、1つずつ判定される
  • どれにも一致しない操作:モードに従う(「手動」なら確認、「自動」なら分類器が判断)

補足:出典は公式の文書 https://code.claude.com/docs/en/permissions です。

権限ルールを調べる順番を示した縦の流れ図。上に「コマンド(例:ansible-playbook ...)」とある。「deny に一致する?」で「はい」なら赤い矢印で「拒否する」へ。「いいえ」なら下の「ask に一致する?」へ進み、「はい」なら橙の矢印で「必ず確認(毎回)」へ。「いいえ」なら「allow に一致する?」へ進み、「はい」なら緑の矢印で「確認なしで実行」へ。「いいえ」なら一番下の灰色の箱「どれにも一致しない → モードに従う(手動なら確認、自動なら分類器が判断)」へ。結びは「最初に一致したものが決める。具体的なルールが優先されるわけではない」。

公式の文書にある、ルールの細かい決まり

上の箇条書きに、公式の文書の記述を足します。

  • 順番と具体性:公式の文書も、評価は deny、ask、allow の順で、その順で最初に一致したものが結果を決め、ルールの具体性は順番を変えない、と書いている。Bash(aws *) のような広い deny は、Bash(aws s3 ls) のような狭い allow にも一致する呼び出しをすべて止める。allow で deny に例外を作ることはできない。ask と allow の間も同じで、一致する ask は、より具体的な allow が同じ呼び出しに一致していても確認を出す
  • :*:Bash(ls:*) のように末尾に付ける :* は、末尾のワイルドカードの同じ意味の書き方で、Bash(ls:*) は Bash(ls *) と同じコマンドに一致する。:* の形が認識されるのは、パターンの末尾だけ
  • つないだコマンド:Claude Code はシェルの演算子を理解しているので、Bash(safe-cmd *) というルールは、safe-cmd && other-cmd の実行を許可しない。区切りとして認識されるのは &&・||・;・|・|&・&・改行。ルールは、サブコマンドのそれぞれに、独立に一致する必要がある
  • 読み取り専用の組み込みの一覧:ls・cat・echo・pwd・head・tail・grep・find・wc・which・diff・stat・du・cd、そして git の読み取り専用の形は、組み込みの読み取り専用のコマンドとして、どのモードでも確認なしで実行される(作業フォルダーの外のパスについては permissions.blockReadsOutsideWorkingDirectories で変わる)。この一覧は設定で変えられない(これらのコマンドで確認を出したいときは、そのコマンドの ask か deny のルールを足す)。自動モードでは、これらのコマンドも分類器の判定を待つことがある。ただし、cd で別のディレクトリーへ移ってから git を実行する組み合わせ(例:cd other && git status)は、各部分が読み取り専用でも確認になる(移った先の git のフックが動きうるため)。cd の後のリダイレクトの書き込み先が決められないときも確認になる
  • リダイレクト:/dev/null、2>&1 や <&3 のようなファイル記述子の形、here-doc や here-string のような、後ろにファイルが無い対象は、検査されない

つないだコマンドの判定が分かりやすいのは、2>&1 | cat です。ansible-playbook --check --diff ... 2>&1 | cat は、前の部分が allow のルールに一致し、2>&1 は検査されず、cat は読み取り専用の一覧にあるので、全体が許可のままになります。


前方一致の落とし穴と、denyの限界

ルールは前方一致

ルールは前方一致です。

  • ルールは前方一致:Bash(ansible-playbook --check *) は、ansible-playbook --check ... で始まるコマンドにだけ一致する
  • 順番が違うと一致しない:ansible-playbook site.yml --check は対象外。確認が求められたり、「自動」では分類器の判断になったりする
  • 対策:CLAUDE.md に、コマンドを書く順番を決めて書いておく(第4回の「チームで共有するCLAUDE.mdのひな形(筆者の例)」の「よく使うコマンド」)
  • deny は境界ではない:/usr/bin/curl や sh -c '...' のように書き方を変えると、deny ルールをすり抜けることがある
  • 確実に止めたいとき:サンドボックスか、PreToolUse フック(第7回の「フックで止める」)を使う
許可のルール(allow)Bash(ansible-playbook --check --diff *) に一致するコマンドと一致しないコマンドを並べた図。前方一致で、先頭が「ansible-playbook --check --diff 」で始まるコマンドにだけ一致する。緑の枠「一致する(確認なしで実行)」の例は、ansible-playbook --check --diff -i inventory/stg/hosts.ini site.yml と、それに 2>&1 | cat を付けたもの(|(パイプ)でつないだものは1つずつ判定される。実機の確認では許可のまま)。赤い枠「一致しない(確認になる。「自動」では分類器の判断)」の例は、順番が違う ansible-playbook site.yml --check --diff(前方一致なので、先頭が合わないと一致しない)。この枠の対策は、CLAUDE.md に、コマンドを書く順番を決めて書いておくこと。灰色の枠「筆者の実測:別のルール Bash(ansible-lint *) の場合」には2行ある。緑の丸印の ansible-lint --version; echo done は、つないでも、echo は通った(確認なしで実行)。赤い×印の ansible-lint --version; echo "exit=$?" は、$? の展開を含むと、確認になった(ansible-lint の部分も実行されない)。最後のオレンジの枠は「deny は境界ではない」で、/usr/bin/curl ... や sh -c '...' のように書き方を変えると、deny のルールをすり抜けることがある。確実に止めたいときは、サンドボックスか PreToolUse フックを使う。

補足:出典は公式の文書 https://code.claude.com/docs/en/permissions です。公式のページには Ansible の例がないため、次の「Ansibleの作業での設定例」の設定で、筆者が実機で確かめました(2026-10-18、CLI の Claude Code 2.1.289、「手動」に当たる --permission-mode default)。順番を変えたコマンドは承認が要り、2>&1 | cat を付けたものは許可のままでした。

筆者の演習でも、ansible-lint; echo "exit=$?" が、allow のルール(Bash(ansible-lint *))があっても確認になりました(2026-10-18、CLI の claude -p。承認が要るものは拒否されます)。同じルールで、別々に実行した追加の実測(--permission-mode default=「手動」)の結果は次のとおりです。

コマンド結果
ansible-lint --version確認なしで実行
ansible-lint --version; echo done確認なしで実行
ansible-lint --version; echo "exit=$?"承認が要って止まった(ansible-lint の部分も実行されない)
ansible-lint --version && echo ok確認なしで実行

筆者の実測では、; や && でつないだことや echo ではなく、$? の展開(変数の展開)を含む部分が確認の原因と見られます。公式の文書では、この挙動の記述を見つけられていません。

公式の文書にある、deny の限界

公式の文書は、Bash のルールの限界を次のように書いています。

  • Bash のルールは、Claude Code が複合コマンドを分け、ラッパーを外した後の、Claude が書いたコマンドの文字列に一致する。同じプログラムを別の形で呼び出したものには一致しない。そのため、deny や ask のルールは、Claude が普通に出す呼び出しをカバーするだけで、プログラムの周りのセキュリティの境界ではない
ルール止めるもの止めないもの
Bash(curl *)curl https://example.com/usr/bin/curl https://example.com、sh -c 'curl https://example.com'
  • deny のルールは、パスで呼んだ同じプログラムや sh -c の中には一致しない。制限を守らせる必要があるときは、サンドボックスのネットワークの許可リストと組み合わせる
  • コマンドの文字列に頼らず、ファイルシステムとネットワークで強制したいときは、サンドボックスを使う

サンドボックスについて、公式の文書は次のように書いています。

  • サンドボックスは macOS・Linux・WSL2 で動く。ネイティブの Windows では、Claude Code はサンドボックスなしでコマンドを実行する。Windows で使うなら、WSL2 のディストリビューションの中で Claude Code を動かす
  • サンドボックスが対象にするのはシェルのコマンドだけ。Claude のファイルのツール・MCP サーバー・フックは、サンドボックスの外で動く
  • サンドボックスは既定ではオフ

Read の deny は、Bash の cat も止めるか

.env を読ませたくないときは、Read(./.env) や Read(./secrets/**) のような Read の deny ルールを書きます。公式の文書は、Read と Edit の deny ルールが、Claude のファイルのツールに加えて、Bash の中で Claude Code が認識するファイルのコマンド(cat・head・tail・sed・tee など)と、リダイレクトの対象(> file・< file)にも効くと書いています。一方、ファイル名を挙げずに読むコマンド(ファイルのあるディレクトリーで実行する grep -r pattern . など)や、Python・Node のスクリプトが自分でファイルを開く場合には効きません。組み込みの Grep・Glob、プロンプトの @file、接続した IDE が渡す選択範囲や開いているファイルにも、Read のルールを best-effort(できる限り)で適用する、とも書いています。

筆者が確かめ直したとき(2026-10-18、CLI の Claude Code 2.1.289)は、まず CLAUDE.md の「.env と vault_pass.txt を読まない」の指示が先に効いて、Claude が cat .env も ansible-vault view vault_pass.txt も自分で実行しませんでした。CLAUDE.md のその行を一時的に外して頼むと、どちらも「Permission to use Bash with command cat .env has been denied.」のように拒否されました。Read(./.env) の deny は、Claude Code が見分けられる cat などのファイルのコマンドにも効きます(公式の permissions の文書の注意と一致)。ただし、名前を挙げずに読むコマンド(grep -r など)や自分でファイルを開くスクリプトには効かないので、そこまで止めたいものは、サンドボックス(OS のレベルの制限)やフックで守ります。連載「Claude活用入門」第5回の「秘密情報を読ませない」にも、同じ注意があります。


設定ファイルの階層

ルールは、設定ファイルのどこに書くかで、効く範囲と強さが変わります。

優先順位ファイル用途
1(最優先)管理ポリシー(managed-settings)組織が配る。利用者は上書きできない。個人の PC では、自分で置かない限り無い
2コマンドラインの指定その回だけ(CLI)
3.claude/settings.local.jsonこのリポジトリでの自分用(Git で共有しない)。「常に許可」の保存先
4.claude/settings.jsonこのリポジトリの共通設定(Git で共有する)。チームで共有するひな形はここ
5~/.claude/settings.json自分の全プロジェクト共通
設定ファイルの階層を、上ほど強い順に5段で並べた図。左の矢印は「強い」から「弱い」へ向かう。1(最優先)は管理ポリシー(managed-settings)で、利用者は上書きできない。組織が配るもの。2はコマンドラインの指定で、その回だけ(CLI)。3は .claude/settings.local.json で、このリポジトリでの自分用。「常に許可」の保存先。Git で共有しない。4は .claude/settings.json で、このリポジトリの共通設定。Git で共有する。5は ~/.claude/settings.json で、自分の全プロジェクト共通。下の枠に、permissions.allow などのリストは、上書きではなく全部合わせて使われる。どこか1か所で deny されたものは、ほかで allow できない、とある。図の見出しは「設定ファイルの階層(上ほど強い)」、最下行は「場所ごとに強さが決まり、リストは合算される」。

補足:permissions.allow などのリストは、上書きではなく全部合わせて使われます。どこか1か所で deny されたものは、ほかで allow できません。公式の文書も、permissions.allow のように同じリストのキーを複数のファイルに書くと、Claude Code は1つを選ばずにリストを結合するので、各ファイルは、ほかのファイルのエントリーを消さずに、エントリーを足せる、と書いています。

CLI では、どのファイルが読まれたかを /status の Setting sources 欄で確認できます(Setting sources の行に、User settings や Project local settings のように、そのセッションで読み込んだ設定ファイルが並びます)。Code タブの /status で、設定ファイルごとの一覧が出るかどうかは、筆者は確かめていません。出典は公式の文書 https://code.claude.com/docs/en/settings です。

未信頼のフォルダーでは、プロジェクトの allow が効かない

.claude/settings.json(プロジェクトの共通設定)に書いた permissions.allow のルールと permissions.additionalDirectories は、Claude に権限を与えるものです。そのため、Claude Code は、そのフォルダーのワークスペースの信頼の確認に応じた後にだけ適用します。

  • 親のフォルダーだけを信頼していた場合:信頼の確認にもう一度応じるまで使われない。確認の画面には、そのルールが一覧で出る
  • claude -p や SDK で、そのフォルダーを一度も信頼していない場合:使われない。Claude Code は this workspace has not been trusted という警告を stderr に出す
  • 信頼の確認は、対話のセッションだけで出る。claude -p や SDK のセッションには出ない

筆者の CLI での実測(2026-10-18、Claude Code 2.1.289)でも、初めてのフォルダーを「信頼」する前は、.claude/settings.json の allow のルールが無視されました(Ignoring 6 permissions.allow entries from .claude/settings.json: this workspace has not been trusted. と表示)。対話の画面で一度開いて信頼の確認に答えると効きました。Code タブでの表示は確かめていません。

組織のプランの補足:管理された設定の配り方

階層の1番目の管理ポリシーは、組織が配るものです。公式の文書では、次のような配り方があります。

  • ファイル:macOS は /Library/Application Support/ClaudeCode/managed-settings.json、Linux と WSL は /etc/claude-code/managed-settings.json、Windows は C:\Program Files\ClaudeCode\managed-settings.json
  • MDM:macOS の構成プロファイルや Windows の HKLM のレジストリ値として、Jamf・Intune・グループポリシーなどのツールで配る
  • サーバー管理の設定(claude.ai の管理画面):Claude for Teams か Claude for Enterprise のプランが要る

ファイルや MDM による配り方に、Team・Enterprise だけという制限は、見つけた範囲の文書には書かれていませんでした。個人で自分の PC を使うなら、自分で置かない限りこの段は空なので、意識する必要はありません。


Ansibleの作業での設定例(筆者の例)

ここまでの決まりを使って、Ansible の作業での設定例を示します。Ansible のリポジトリの .claude/settings.json(Git で共有する)に置きます。第8回の演習の準備プロンプトで作る設定と同じものです。

{
  "permissions": {
    "allow": [
      "Bash(ansible-lint *)",
      "Bash(ansible-inventory *)",
      "Bash(ansible-playbook --syntax-check *)",
      "Bash(ansible-playbook --check --diff *)",
      "Bash(git diff *)",
      "Bash(git status *)"
    ],
    "ask": [
      "Bash(ansible-playbook * inventory/prod*)",
      "Bash(git push *)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./**/vault_pass*)",
      "Bash(ansible-vault decrypt *)",
      "Bash(ansible-vault view *)"
    ]
  }
}
  • allow(確認なしで実行):lint・インベントリーの確認・構文確認・--check --diff(変更を加えずに差分を見る実行)・git の差分と状態
  • ask(毎回確認):インベントリーのパスに inventory/prod が入る ansible-playbook(本番を指すもの)と、git push
  • deny(拒否):.env と、vault_pass で始まるファイルの読み取り、Vault の復号と表示

この設定は筆者の例で、公式の推奨ではありません。


設定例の読み方と、使い分け

設定例が、モードごとにどう動くかを表にします。

場面モード設定例での動き
調べる・計画するプラン読み取りと、分類器が認めた調査用のコマンドだけ
書かせてレビューする編集を受け入れるlint・構文確認・stg への –check –diff は確認なし。stg への本実行は確認が出る
長く任せる自動上と同じものは確認なし。どれにも一致しないものは分類器が判断する
本番の作業手動prod を指すものは、–check でも必ず確認が出る(ask は allow より先に評価される)
どのモードでも—.env や Vault のパスワードは読ませない。Vault の復号はさせない

補足:この設定は筆者の提案で、公式の推奨ではありません。表のうち「手動」の動きは、筆者が 2026-10-18 に CLI の Claude Code 2.1.289(--permission-mode default)で13件のコマンドを試して確かめました。lint・構文確認・stg への --check --diff(2>&1 | cat 付きも)と、&& でつないだ lint と構文確認は確認なしで実行され、順番を変えた --check --diff、stg への本実行、prod を指す --check --diff(2>&1 | cat 付きも)、git push は承認が要りました。ansible-vault view と cat .env は、前の節のとおり Claude が実行しませんでした。第4回のひな形(「チームで共有するCLAUDE.mdのひな形(筆者の例)」)どおりに 2>&1 | cat を付けても、同じように判定されます。

表のうち、いくつかの動きを補います。

  • prod を指すものは、--check でも確認が出る:ansible-playbook --check --diff -i inventory/prod/hosts.ini site.yml は、allow の Bash(ansible-playbook --check --diff *) にも、ask の Bash(ansible-playbook * inventory/prod*) にも一致します。ask が先に評価されるので、確認になります
  • 「自動」でも ask は確認が出る:公式の文書は、auto mode でも、ask のルールが出させる確認は引き続き出る、と書いています。git push を、auto mode の分類器に任せずに確認させたいときに使えます(第5回の「公式の文書にある、表に載せなかった項目」で見たように、auto mode は既定のブランチへの通常の push を通すため)
  • stg への本実行は確認が出る:allow にあるのは --syntax-check と --check --diff だけなので、--check を付けない本実行は、どのルールにも一致せず、モードに従います。筆者の演習の記録(2026-10-18、CLI、--permission-mode default=「手動」)でも、stg への本実行(ansible-playbook --diff -i inventory/stg/hosts.ini site.yml)は承認待ちになり、承認されなかったので実行されませんでした
  • 「常に許可」で足されるもの:Code タブで、その確認に「常に許可」を選ぶと、.claude/settings.local.json に {"permissions":{"allow":["Bash(ansible-playbook -i inventory/stg site.yml)"]}} が保存され、同じ依頼の2回目は確認が出ませんでした(2026-10-04、Code タブ 2.1.284)。そのコマンドだけに一致するルールで、パイプの 2>&1 | cat は外されていました。この形を、この回のルールの書き方と比べてみてください

この回の内容は、第9回の演習の手順6(「手動」のまま stg への本実行を頼み、確認の画面で「常に許可」を選んで、.claude/settings.local.json を開く)で試せます。


考えてみよう

  1. allow に Bash(ansible-playbook --check *) だけがあるとき、ansible-playbook site.yml --check は確認なしで実行されますか。実行されない場合、どうすれば確認を減らせますか。
  2. allow に Bash(git push origin feature/*)、ask に Bash(git push *) があるとき、git push origin feature/x は確認なしで実行されますか。理由も答えてください。
  3. .env を読ませたくありません。Read(./.env) の deny だけで十分でしょうか。確実に止めたいなら、ほかに何を使いますか。

ヒント:1は「前方一致の落とし穴と、denyの限界」、2は「allow・ask・denyルールの書き方」の評価の順番、3は「Read の deny は、Bash の cat も止めるか」の節を見直してください。


まとめ

  • ルールは ツール名(条件) の形。deny → ask → allow の順に調べ、最初に一致したものが決める。具体的なルールが優先されるわけではなく、広い deny に狭い allow で例外は作れない
  • ask に一致したものは、狭い allow があっても使うたびに確認になる。どれにも一致しないものは、モードに従う
  • ルールは前方一致で、つないだコマンドは1つずつ判定される。順番が違うと一致しないので、CLAUDE.md にコマンドの書く順番を決めておく
  • deny は境界ではない。/usr/bin/curl や sh -c '...' で書き方を変えると、すり抜けることがある。確実に止めたいなら、サンドボックスか PreToolUse フック
  • 設定は、管理ポリシー、コマンドライン、.claude/settings.local.json、.claude/settings.json、~/.claude/settings.json の順に強い。リストは合算され、どこかで deny されたものは、ほかで allow できない
  • プロジェクトの allow は、ワークスペースの信頼の確認に応じた後にだけ効く
  • 設定例は、allow に lint・構文確認・--check --diff、ask に prod への実行と git push、deny に .env と Vault の復号を置く(筆者の例。公式の推奨ではない)

次回は、「走らせたら終わり」にしないための検証を扱います。


連載「Claude Code実践入門」全9回

  1. 任せる前に知っておくこと
  2. 作業範囲を決める
  3. 走らせながら操縦する
  4. CLAUDE.mdを育てる
  5. 権限モードとauto mode
  6. allow・ask・denyのルールと設定ファイル(この記事)
  7. 検証で終わらせる
  8. 演習(前編):準備から実装と検証まで
  9. 演習(後編):巻き戻し・差分・権限と振り返り

コメント

タイトルとURLをコピーしました