Microsoft Execution Containers(MXC)は、10月7日にSDKの1.0.0が出た。ただ、Claude Codeは対応一覧で「Coming soon」の側にあり、MXCは入れれば効くツールでもない。Macで使える閉じ込め方式はSeatbeltの1種類で、許可リストづくりを助けるLearningモードはWindows専用だ。
「MXCが出たから、Claude Codeを使っても大丈夫だろう」と言われたら、何と答えるか?
許可したものを後から一覧で説明できるか。判断の基準はそこだ。
MXCはClaude Codeを包むツールなのか?
違う。リポジトリのREADMEには「MXC is an SDK dependency that builds into your app.」とある。エージェントを作る側がSDKを組み込み、そのアプリの中から子プロセスを閉じ込めて動かす仕組みだ。
MicrosoftのWindows Developer Blogの発表で対応済みとして並ぶのは、GitHub Copilot、OpenClaw、OpenAI Codex、Replit、LM Studio、Unsloth AIなどだ。Claude Codeは、Hermes Agent、Perplexity、RaycastなどとともにComing soonに入っている。
つまり、Claude CodeをMXCの中で動かしたければ、今は自分で包むしかない。Node・.NET・RustのSDKから呼ぶか、Macならmxc-exec-macという実行ファイルにJSONのポリシーを渡す。あなたの組織に、その包む部分を書いて保守する人はいるだろうか?
MacのMXCで、.envに効く設定と効かない設定
Macでの方式はSeatbeltだけだ。App Sandboxと同じカーネルの仕組みで、要件はmacOS 15以降。rootも常駐プロセスもインストールも要らない、とSeatbeltの公式文書にある。
deniedPathsの優先度説明のしやすさで見ると、deniedPathsが他の許可より常に勝つ点はありがたい。広いフォルダを読み書き可にしても、.envを禁止に書いておけば禁止が残る。環境変数を引き継がない点も、APIキーを何に渡したかを列挙しやすくする。
一方で、「api.anthropic.comだけ通す」はSeatbelt単体では書けない。通信をホスト名で絞るには、ローカルのプロキシを挟んでプロキシ側に許可リストを持たせる構成になる。外向きを全部止めれば、Claude Codeはモデルに問い合わせられず仕事にならない。
.envと.sshを塞ぐポリシーの書き方
公式のQuick startの形に、プロジェクトの.envを足すとこうなる。macOS用のJSONで、私は実行していない。
{
"version": "0.9.0-alpha",
"containment": "seatbelt",
"process": { "commandLine": "echo hi", "timeout": 30000 },
"filesystem": {
"readwritePaths": ["/Users/me/project"],
"deniedPaths": ["/Users/me/.ssh", "/Users/me/project/.env"]
},
"network": {
"egress": { "default": "deny" },
"ingress": { "default": "deny", "hostLoopback": "deny" }
}
}./mxc-exec-mac --dry-run config.jsonとすれば、動かさずに設定だけを検証できる。文書も「always run --dry-run first」と勧めている。
公式が警告している抜け道もある。Docker、ssh-agent、gpg-agentのソケットは、読み書き可のパスの下にあると接続できてしまう。読み書きを許すフォルダは狭く取り、ソケットは禁止に入れる。.envだけ見ていると見落とす。
Node 22でMXCのSDKを試すと、ここで止まる
使い捨てのLinuxコンテナ(node:22-bookworm)で、Node SDKの@microsoft/mxc-sdkを入れて試した。ダミーのキーを入れた.envとダミーの鍵を用意し、次のポリシーで中身を表示させるスクリプトを書いた。
{
containment: { type: 'process' },
filesystem: { readwritePaths: ['/work/proj'], deniedPaths: ['/work/proj/.env', '/root/.ssh'] },
network: { egress: { default: 'deny' } },
workingDirectory: '/work/proj',
}最初のつまずきはバージョンだ。npm i @microsoft/mxc-sdkと指定なしで入れると、約3.1秒で入ったのは0.8.0だった。npmのlatestは1.0.0なのに、Node 22の環境では選ばれなかった。0.8.0では公式サンプルと同じimport { run } from '@microsoft/mxc-sdk/v1'が通らない。
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './v1' is not defined by "exports"@1.0.0と明示すると入るが、EBADENGINE required: { node: '>=24.0.0' }の警告が出る。1.0.0はNode 24以上が前提だ。手元の端末のNodeは何系だろうか?
1.0.0で実行すると、Linuxの既定方式であるbubblewrapが起動せず、exitCode 1で終わった。
bwrap: No permissions to create new namespace, likely because the kernel does not allow non-privileged user namespaces.Dockerコンテナの中では、bubblewrapに必要な名前空間を作れなかった。だから.envが本当に読めなくなるかは、この検証では確かめられていない。ここまでで言えるのは、ポリシーは短く書けること、失敗時のエラーが足りない権限を名指しすることの2点だ。
Claude Codeの.envを今日隠すなら、標準のsandbox
Claude Codeには標準のsandboxがある。MacではMXCと同じSeatbelt、LinuxとWSL2ではbubblewrapを使う。既定では~/.sshや~/.aws/credentialsを含むマシンのほぼ全体を読めるので、sandbox.filesystem.denyReadやsandbox.credentialsで塞ぐ。
落とし穴は、sandboxがシェルコマンドしか包まない点だ。ReadやEditなどのファイル操作ツール、MCPサーバー、hooksは外で動く。公式も「A denyRead entry doesn't stop the Read tool」と書いている。cat .envは止まっても、Readツールで開かれたら読める。
{
"permissions": {
"deny": ["Read(./.env)"]
},
"sandbox": {
"filesystem": { "denyRead": ["~/.ssh"] }
}
}permissions.denyのRead(./.env)がファイル操作ツール側、denyReadがシェル側を受け持つ。2か所に書くことになるが、どちらも設定ファイルに残るので、何を禁じたかは後から読み返せる。
組織で配るなら、managed settingsを使う。managed settingsでsandbox.filesystemを設定すると、ファイルの隔離を切るfilesystem.disabledはmanaged settingsからしか変えられなくなる。MXCのほうは、Intuneでの管理がまだ「soon」の段階で、対象もWindows 11だ。
許可したものを説明できるのは、どちらのsandboxか
今日の時点で私が選ぶなら、Claude Code標準のsandboxとpermissions.denyを組み合わせ、managed settingsで配る。禁じたものが設定ファイルにまとまり、利用者の設定ではファイルの隔離を切れないからだ。
ただし標準のsandboxは、環境変数を既定でClaude Codeから引き継ぐ。秘密を入れた環境変数はsandbox.credentialsで外す必要がある。この点は、何も渡さないところから始まるMXCのほうが説明しやすい。弱いのはClaude Code側の対応と管理手段がまだ無いことで、Coming soonが外れ、Intuneで配れるようになった時点で比べ直せばよい。
利用者のClaude Codeに何を禁じたか、今すぐ一覧で出せるだろうか。出せないなら、まずRead(./.env)の1行から書き始めるとよい。
コメント
ログイン か 会員登録 するとコメントできます