[Claude Code] チーム・組織で使うためのセキュリティ設定 ― 権限とdeny、managed settings

Tech
[Claude Code] チーム・組織で使うためのセキュリティ設定 ― 権限とdeny、managed settings

このブログの改善も Claude Code に手伝ってもらっていますが(その話はこの記事)、個人で使うぶんには「まあ好きにやってくれ」で済みます。ところがチームや組織に配るとなると話が別。エージェントは有用な操作と危険な操作を必ずしも区別しないので、.env を読ませない・本番を壊させない、といったガードレールを先に敷いてから渡す必要があります。

メルカリさんの Claude Code セキュリティ設定の組織配布戦略(Claude Code Meetup Japan #4)が良い整理だったので、公式ドキュメントで裏を取りつつ、要点を自分用にまとめておきます。

⚠️ Claude Code は更新が速く、設定キーや既定の挙動が変わります。本記事は考え方の整理として読み、実際に組織へ適用する前に必ず公式ドキュメントで最新の記法を確認してください。

設定ファイルの階層と優先順位

Claude Code の設定は複数のレイヤーに分かれ、上のものが下を上書きします。組織統制の要は最上位の managed settings です。

レイヤーファイル用途
managed(組織)OSごとのシステムパス(下記)管理者が配布。開発者は上書き不可
ローカル(個人).claude/settings.local.jsongitignore。自分専用
プロジェクト共有.claude/settings.jsongit にコミットしてチーム共有
ユーザー~/.claude/settings.json自分の全プロジェクト共通

managed settings のパスは OS で異なります。

OSmanaged settings のパス
macOS/Library/Application Support/ClaudeCode/managed-settings.json
Linux / WSL/etc/claude-code/managed-settings.json
WindowsC:\Program Files\ClaudeCode\managed-settings.json

ポイントは、managed の deny は誰も上書きできないという点。ユーザーが自分の設定で allow しようが、managed の deny が勝ちます。ここが組織ガバナンスの背骨になります。

権限は3種類、評価は deny → ask → allow

権限ルールは3タイプ。

  • allow … 確認なしで実行
  • ask … 実行のたびに確認プロンプト
  • deny … 実行そのものをブロック

評価順が重要で、deny → ask → allow の順にマッチを見て、最初に当たったもので決まります。ルールの具体性(細かさ)は順番を変えません。つまり広い deny が狭い allow を確実に潰せる、ということです。

{
  "permissions": {
    "allow": [
      "Bash(npm run test:*)",
      "Read(./src/**)"
    ],
    "ask": [
      "Bash(git push:*)"
    ],
    "deny": [
      "Bash(rm -rf *)"
    ]
  }
}

記法の勘どころ

ツールごとに書き方が違います。よく使うものだけ。

  • Bash … コマンドの前方一致* ワイルドカード。Bash(npm run test:*)npm run test で始まる呼び出しにマッチ。Bash(ls *) は空白で区切って ls -la に当たり、Bash(ls*)lsof にも当たってしまう(境界に注意)
  • Read / Edit.gitignore 風のパスマッチ。Read(.env) はどの階層の .env にも当たり、~/ はホーム、** はディレクトリ横断
  • WebFetch … ドメイン単位。WebFetch(domain:example.com)、サブドメインは WebFetch(domain:*.example.com)
  • MCPmcp__<サーバー名>__<ツール名>mcp__github__* でそのサーバーの全ツール、mcp__* で全 MCP

複合コマンド(&&| でつないだもの)は、各サブコマンドが個別にマッチ判定されます。git push を ask にしていても foo && git pushgit push 部分がちゃんと拾われる、ということです。

シークレットは「ブロック」ではなく「見せない」

ここが一番のキモ。.env や鍵ファイルは denyRead() で塞ぐのが正解です。

なぜフック(後述)より deny が良いか。deny ルールに入れたファイルは、そもそも Claude のコンテキストに入りません。モデルが中身を見ないので、出力から漏れる経路自体が消えます。一方フックは「読もうとした後にブロック」なので、ファイルの存在や試行の痕跡は残り得る。ブロックするより、最初から見せないほうが安全、という発想です。

{
  "permissions": {
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(./secrets/**)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)",
      "Read(~/.config/gcloud/**)",
      "Read(~/.kube/config)"
    ]
  }
}

これを managed settings に置けば、開発者は外せません

組織で最初に deny しておきたいもの

シークレット以外にも、事故りやすいものを先に塞ぎます。

{
  "permissions": {
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)",

      "Edit(.github/workflows/**)",
      "Edit(./deploy/**)",
      "Edit(./terraform/**)",

      "Bash(rm -rf *)",
      "Bash(git push --force:*)",
      "Bash(git reset --hard:*)",
      "Bash(terraform destroy:*)",
      "Bash(kubectl delete:*)"
    ]
  }
}
  • シークレット / 鍵.env~/.ssh、クラウド認証情報
  • CI/CD・インフラ定義.github/workflowsdeploy/terraform/(勝手に書き換えさせない)
  • 破壊的コマンドrm -rfgit push --forcegit reset --hardterraform destroy など

動的なチェックは hooks で

「パス名やコマンド接頭辞で機械的に決められる」ものは deny/allow で十分。一方、URL の中身を見て判断したい・ファイルサイズや git の状態で分岐したい、みたいな動的な判定は PreToolUse フックの出番です。

フックはツール実行の前に走るスクリプトで、標準出力の JSON や終了コードで「通す/確認する/止める」を返せます。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          { "type": "command", "command": "~/.claude/hooks/guard.sh" }
        ]
      }
    ]
  }
}

使い分けはシンプルに、静的なポリシー = deny ルール / 動的な判定 = フック。そしてmanaged の deny はフックが allow を返しても勝つので、「絶対に触らせたくないもの」は deny 側に置くのが鉄則です。

権限モードと「危険なスキップ」

Claude Code には権限モードがあり、defaultMode で既定を指定できます。

  • default … 読み取り以外は都度確認(慎重・初期向き)
  • acceptEdits … 編集まで自動(レビューしながら回すとき)
  • plan … 変更前に計画だけ立てさせる
  • bypassPermissions … 全部素通り

--dangerously-skip-permissions(いわゆる bypass)は隔離されたVM・コンテナ以外では使わないのが大原則。組織としては、managed settings で bypass モード自体を禁止しておくと安全です(disableBypassPermissionsMode などのキーがあります。最新の記法は公式ドキュメントで確認を)。

MCP サーバーの統制

外部ツールを生やす MCP も統制対象です。managed settings 側で使ってよいサーバーを許可制にでき(allowedMcpServers / deniedMcpServers)、権限ルールでも mcp__ 単位で絞れます。

{
  "permissions": {
    "allow": ["mcp__github__*"],
    "deny": ["mcp__*"]
  }
}

「原則すべての MCP を deny、業務で使うものだけ allow」に倒すと、野良 MCP の混入を防げます。

組織へ「配布」する

ここがメルカリさんの資料の主眼でもある部分。ローカルに設定を置くだけでは開発者が外せてしまうので、外せない形で配る必要があります。

  • MDM / OSポリシーで配布(Jamf・Intune・Group Policy 等)→ 上記のシステムパスに managed-settings.json を配置。OSレベルで固定でき、いちばん堅い
  • サーバー管理設定(Claude for Teams/Enterprise の管理コンソール)→ 起動時と定期的に取得。ネットワーク前提だが一元管理しやすい

要は、deny を書くだけでなく「開発者が外せない層(managed)に置いて配る」までがワンセット。ここまでやって初めて「組織のガードレール」になります。

まとめ

  • 設定は階層構造で、managed settings は開発者が上書きできない=組織統制の要
  • 権限は deny → ask → allowdeny が常に勝つ
  • シークレットは deny の Read() で「見せない」(フックでブロックより上)
  • .env・鍵・CI定義・破壊的コマンドは先に deny
  • 動的判定は PreToolUse フック、bypass モードは原則禁止
  • 最後は managed settings として MDM 等で配布して、外せない形にする

個人利用と組織利用では、Claude Code に求める“設計”がまるで違います。チーム導入を考えているなら、コードを触らせる前に、まずこのガードレールから。

参考リンク

Claude Code, セキュリティ, AI