Claude Media
allowManagedModsOnlyでユーザー導入のmodを止める — Claude Code

allowManagedModsOnlyでユーザー導入のmodを止める — Claude Code

Claude Codeのmodを組織で管理する設定です。built-in guardにallowManagedModsOnlyを置く書き方、自組織のmodだけ通す構成、効いているかの確かめ方をまとめます。

allowManagedModsOnlyでユーザー導入のmodを止める — Claude Code

allowManagedModsOnlyは、ユーザーが持ち込んだmodのhookを1つも動かさないための設定です。managed settingsのpluginConfigsに、built-in guardのオプションとして書きます。ユーザー側の設定ファイルに同じ行を書いても効きません。

mod(Claude Code内で動くコードを含むプラグイン)は、サンドボックスの外で、導入したユーザーの権限のまま動きます。プロンプトもツール呼び出しも見えて、書き換えられます。組織が配るマシンでこれを野放しにするか、止めるか、自社のmodだけ通すか。その3択を設定で決める手順をここにまとめます。modを作る側の話はClaude Codeのmodを80行で作るにあります。

allowManagedModsOnlyは何を止める設定か

allowManagedModsOnlyは、Claude Codeが標準で読み込む「built-in guard」のオプションです。guardの正式なidはcc-plugin-sec-default@builtinで、/pluginやデバッグログではcc-plugin-sec-defaultと表示されます。ユーザーはguardを無効にできません。

オプションをtrueにすると、動くのは次の2種類だけになります。

  • 自組織のmod
  • Claude Codeに組み込み済みのmod(AGENTS.md対応など)

それ以外のmodは、ユーザーが入れたプラグイン内のmodも、--plugin-dirで指したmodも、セッション中にClaudeが書いたmodも拒否されます。この設定が使えるのはmodsが既定で有効になったv2.1.286以降の環境です。経緯はClaude Code v2.1.287のリリースノートにあります。

managed settingsへの書き方

managed settings(ファイル配布、MDM、claude.aiの管理画面のいずれか)に、次の1ブロックを足します。

{
  "pluginConfigs": {
    "cc-plugin-sec-default@builtin": {
      "options": {
        "allowManagedModsOnly": true
      }
    }
  }
}

キーのidに注意してください。pluginConfigsが受け付けるのはcc-plugin-sec-default@builtinの形だけです。後述のprependPluginsではsec-default@builtinと書くので、2つを混同しやすい箇所です。

配布経路による違いは1点あります。ファイルまたはMDMで配ると、Amazon Bedrock、Google CloudのAgent Platform、Microsoft Foundryのどれでも同じ動きになります。claude.aiの管理画面から配る場合は、Server-managed settingsの「Platform availability」で対象の面を確かめます。

止まるものと止まらないもの

効果の範囲は狭く、そのぶん予測しやすい設定です。

対象allowManagedModsOnly後の動き
ユーザーが入れたプラグイン内のmodallowManagedModsOnly後の動きhookが動かない
--plugin-dirで読み込むmodallowManagedModsOnly後の動きhookが動かない
セッション中にClaudeが書いたmodallowManagedModsOnly後の動きhookが動かない
自組織のmodallowManagedModsOnly後の動き動く
Claude Code組み込みのmodallowManagedModsOnly後の動き動く(それぞれ個別のスイッチを持つ)
settings内のhook、プラグインのhooks/hooks.jsonallowManagedModsOnly後の動き影響なし
ステータスライン、/goalallowManagedModsOnly後の動き影響なし

止めるのはmodだけで、既存のhook資産は巻き込みません。hookごと止めたいなら、後で比べるallowManagedHooksOnlyやdisableAllHooksの領分です。

自組織のmodだけを通す構成

「全部止める」ではなく「自社のmodは動かす」場合は、modを自組織のものとしてClaude Codeに認識させる必要があります。認識されるのは、次の3条件がそろったときだけです。

  • managed settingsのenabledPluginsでそのプラグインがtrue
  • managed settingsがそのマーケットプレイスを、ユーザーのマシン上のディレクトリとして絶対パスで指している(extraKnownMarketplacesで書けます)
  • マーケットプレイスがプラグインを相対パスで列挙していて、Claude Codeがそのディレクトリのまま読み込める

条件を満たす完全なmanaged-settings.jsonは次のとおりです。例のacme-guardは、マーケットプレイスのacme-toolsが置いてあるディレクトリ内の自社mod、という想定です。

{
  "extraKnownMarketplaces": {
    "acme-tools": {
      "source": { "source": "directory", "path": "/opt/acme/claude-plugins" }
    }
  },
  "enabledPlugins": { "acme-guard@acme-tools": true },
  "prependPlugins": ["acme-guard@acme-tools", "sec-default@builtin"],
  "pluginConfigs": {
    "cc-plugin-sec-default@builtin": {
      "options": { "allowManagedModsOnly": true }
    }
  },
  "disableSideloadFlags": true
}

各キーの役割は次のとおりです。

  • extraKnownMarketplaces、enabledPlugins、prependPlugins: 自社modを導入し、guardの手前で先に走らせる
  • pluginConfigs: ユーザーのmodを拒否する
  • disableSideloadFlags: --plugin-dirと--plugin-urlを起動時に拒否し、Claudeがセッション中に書いたmodも読み込ませない

ディレクトリの配置は、MDMなどの端末管理で全台の同じパスにコピーします。そのディレクトリと上位ディレクトリは、管理者だけが書き込めるようにします。誰かが書き込めれば、自社modを書き換えられるからです。claude.aiの管理画面から配るmanaged settingsはキーを運べますが、ディレクトリそのものを端末に置くことはできません。

マーケットプレイス側の制限はClaude Codeプラグインマーケットプレイスの必須化と自動更新設定で扱っています。

効いているかを検証用マシンで確かめる

設定を配ったら、検証用のマシンで次の2通りを試します。

1つ目は、適当なmodのディレクトリを--plugin-dirで渡す方法です。

claude --plugin-dir ./first-mod

設定が効いていれば、そのmodのhookは動きません。トランスクリプトとデバッグログに、modの名前とallowManagedModsOnlyを含むguardのメッセージが出ます。

2つ目は、デバッグログを読む方法です。

claude --debug

ログで見る行は3種類あります。

  • 自社mod: hooks moduleの行にtier prependと出る
  • ユーザーが入れたmod: refused by cc-plugin-sec-default: mods are limited to your organization's by policy (allowManagedModsOnly)の行が出る。手前の行にhooks moduleがloadedと出ていても、拒否の行を探せば足ります
  • disableSideloadFlags込みの構成でclaude --plugin-dir ./any-modを実行した場合: --plugin-dir is disabled by your organization's managed settings (disableSideloadFlags)で始まるメッセージを出して終了する

ログに拒否の行が出ないときは、次の節の条件を上から潰します。

効かないときに疑う5点

オプションが有効になるルールは決まっています。効かないときは、上から順に当てます。

  1. managed settingsに置いたか。ユーザー設定、プロジェクト設定、ローカル設定、--settingsで渡したファイルに同じ行があっても、オプションは設定されず、緩和もされません。
  2. guardが読み込まれているか。guardが動くのは、マシンにmanaged settingsがあるか、ユーザーがTeamまたはEnterpriseプランでサインインしているときです。APIキーやBedrockなどで認証するユーザーは、managed settingsがあるマシンでだけguardを受け取ります。guardが載らない環境では、オプションも効きません。
  3. prependPluginsにguardを書いたか。 prependPluginsを設定すると、リストが既定を置き換えます。built-inのguardを残すにはsec-default@builtinを自分で書きます。guardにenabledPluginsのエントリは要りません。
  4. 自社modが「自社のもの」になっているか。GitHub、git、URL、npmなどのリモートソースから入るプラグインは、Claude Codeがキャッシュにコピーするため、managedのenabledPluginsで有効にしても、ユーザーのmod扱いです。prependPluginsとappendPluginsには無視され、allowManagedModsOnlyにも拒否されます。ユーザーのデバッグログに「is enabled by managed settings, but」で始まる行が出ます。ログで自社modがtier userになっていたら、これが原因です。
  5. 旧環境変数に頼っていないか。次の節で扱います。

なお、guardはfail closedで動きます。managed settingsを読めなければ、ユーザーのmodはロード時に全部拒否されます。

CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=0からの移行

早期アクセス期間にmodを止める手段としてCLAUDE_CODE_ENABLE_FUNCTION_HOOKSを0にしていた場合は、allowManagedModsOnlyへ置き換えます。v2.1.287以降のClaude Codeはこの変数を値に関係なく無視するので、0を設定したままだとmodが有効になります。

移行前後で挙動を見比べるなら、検証用マシンで変数を外し、前節のデバッグログの拒否行が出ることまで確かめます。変数を消す作業と、managed settingsの配布が同じタイミングで終わるとは限りません。変数を消す前にallowManagedModsOnlyを先に配るのが安全な順序です。

設定の使い分け

modの制御に関わる設定は複数あり、止める範囲が違います。

やりたいこと設定
インストール済みmodは止める。settings hookは残す設定allowManagedModsOnly(自社modは置かない)
自社modだけ許可する設定allowManagedModsOnlyと、自社modの導入
承認済みのマーケットプレイスのmodは許す設定マーケットプレイス制限とdisableSideloadFlags: true
自社modで他のmodを検査して許す設定自社modをprependPluginsに、sec-default@builtinと並べる
modもhookも全部止める設定disableAllHooks: true

allowManagedHooksOnlyは、もう少し広い設定です。動くのは自社のmodと組み込みmodだけになり、ユーザー自身の設定ファイルにあるhookもブロックされます。disableAllHooksは最も広く、managed settingsに置くと自社modもmanaged hookも止まります。PreToolUseのblockも効かなくなるため、使う前に設定リファレンスの該当節を読んでください。

迷うなら、まずallowManagedModsOnlyから始めるのが影響の小さい選択です。ユーザーが手元で組んだ既存のhookやステータスラインを壊さずに、modだけを閉じられます。

allowManagedModsOnlyで守れないもの

この設定は入口を閉じる仕組みで、modが動いた後の中身を縛る仕組みではありません。許可したmodは、ユーザーと同じファイル、プロセス、ネットワークの権限で動きます。

もう1つ、deny規則との関係に落とし穴があります。guardが読み込まれている環境では、ユーザーのmodはdeny規則が拒否する呼び出しを承認できません。ただしこれはClaudeのツール呼び出しにかかる話です。modが自分で呼ぶ$.fsや$.processには及ばないので、Read(.env)をdenyにしても、modは$.fs.readで同じファイルを読めます。この種の呼び出しを制限するには、modを読み込ませないか、自社のポリシーmodで該当呼び出しを処理します。

ユーザーのmodを許したうえで中身を検査したい組織には、plugin.registerイベントを受ける自社modが向いています。たとえば、$.process.runや$.process.spawnを呼ぶユーザーのmodをrefuseで拒否する形です。

なお、ユーザーが--safe-modeで起動すると、自社modを含めてインストール済みmodは全部オフになります。modの異常を切り分ける用途の機能で、ポリシーの穴というより、自社modの検査もこの間は走らないという前提で運用を組みます。

まとめ

allowManagedModsOnlyは、managed settingsのpluginConfigsにcc-plugin-sec-default@builtinをキーに置く、1ブロックの設定です。自社のmodがなければこれで終わりで、あるならenabledPlugins、extraKnownMarketplaces、prependPluginsの3キーを足し、自社modを管理者権限のディレクトリに置きます。

配った後は、検証用マシンで--plugin-dirを試し、デバッグログの拒否行まで見るところまでが1セットです。設定ファイルを配っただけでは、置き場所の間違いやguardが載らない環境を見落とします。組織全体の設定の置き場所はClaude Code組織管理ガイドにまとめています。

この記事を共有:XはてブLinkedIn