「外部通信禁止」と言われたので、
Copilot CLIをWSL2に閉じ込めた
GitHub Copilot CLI × WSL2
inoinoino
自己紹介
GitHub: in0ho1no / X: @in0ho1no
普段は組み込み開発
C言語一筋10年 / 趣味でPythonを数年
AIは個人利用が主
業務での利用は推進中
今日の流れ
アジェンダ
背景:外部通信禁止の要件と、案件混在の防止
Copilot Chatでは足りなかった
Copilot CLIをWSL2に閉じ込める
運用に落とす(但し、現場投入はマダ)
まとめ:多層防御の一層と、残る制約
扱う情報によって、求められる機密性は違う
01 背景
多くの案件
AIを普通に使える。Web検索もMCPサーバも使える
ある案件
AIの「Web検索」をオフにするよう求められた。これを「外部通信禁止」と解釈した
それでも、AIは使いたい。いいとこどりをしたい。
求められたことは2つ
01 背景
- 外部通信の遮断
公式サーバ(GitHub)以外へ通信しない
- 案件の分離
案件Aの情報を、案件Bの作業に混ぜない
(ファイル、会話履歴、認証情報)
しかも「設定し忘れ」や「AIによる設定の書き換え」で崩れないこと
エージェント自身が、遮断を認めた
01 先に結論
これを案件ごとに、設定し忘れても崩れない形で作る
VS CodeのSandboxを有効にしても、通信は止まらない
02 Copilot Chatでは足りなかった
- 外向き通信
既定で許可。トグルはオン・オフだけで、通信は止まらない
- fetch・統合ブラウザ
サンドボックスの対象外。別のポリシーで止める必要がある
- Localセッション
対象外。効くのはAgent Hostセッションだけ
案件単位で強制できない
02 Copilot Chatでは足りなかった
分離
VS Code Serverが、案件をまたいで共有される
起動
起動のしかたを揃えられず、案件ごとの設定を強制する入口がない
案件ごとにプロセスを分けて起動できる、Copilot CLIを選んだ
なぜ、WSL2の専用ディストリなのか
03 Copilot CLIをWSL2に閉じ込める
Copilot CLIのサンドボックスは、WindowsではMXCでも動く。それでもWSL2を選んだ
Claude Codeも見据える
Claude Codeのサンドボックスは、ネイティブWindowsでは動かない。WSL2なら同じ構成で揃えられる
案件分離を意識させる
ディストリを丸ごと分ける。プロンプトのホスト名で、今どの案件にいるかが見える
構成:案件ごとに専用ディストリを作る
03 Copilot CLIをWSL2に閉じ込める
3つの層で、止めるものを分担する
03 Copilot CLIをWSL2に閉じ込める
- サンドボックス+管理設定
止める:AIが実行するコマンド
bubblewrapとslirp4netnsで、通信と作業フォルダ外を遮断。管理設定で、緩められない下限を置く
- ランチャー
止める:起動の条件のばらつき
許可リスト外の環境変数を捨て、決まった引数で起動する。直接起動は案内に置き換える
- 専用ディストリ
止める:案件をまたぐ参照
案件ごとに分ける。wsl.confで、Windowsのファイル(
/mnt/c)とアプリ(powershell.exe)への経路を断つ
管理設定で、緩められない下限を置く
03 Copilot CLIをWSL2に閉じ込める
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowBypass": false,
"auth": { "git": false, "gh": false },
"userPolicy": { "network": {
"allowOutbound": false,
"allowLocalNetwork": false
} }
}
- エージェントの手が届かない場所に置く
rootだけが書き込めるファイルにする
- ここより緩められない
ユーザ設定、リポジトリの設定、起動時の引数のどれでも
- 効いているかを見る
条件外は黙って無視される。
/sandboxに(managed)と出るか
検証結果:何がどう遮断されたか
03 Copilot CLIをWSL2に閉じ込める
確認したこと |
結果 |
|---|---|
シェルからの通信(curl) |
名前解決できずに失敗。ネットワークはloだけ |
Web取得・GitHub MCP |
接続できず、ツールは使えない |
作業フォルダ外のファイル |
シェルからは存在ごと隠れ、組み込みツールは拒否 |
トークン・設定ファイル |
|
環境変数の鍵 |
ランチャーで除かれる( |
Windowsアプリ |
command not found |
別の案件 |
別ディストリのファイルは見えない |
メモリ機能 |
有効だと全リポジトリ共通の記憶に入った。無効化後は作業フォルダのAGENTS.mdへ |
Copilot CLI 1.0.107、Ubuntu 24.04.5、bubblewrap 0.9.0、slirp4netns 1.2.1で確認
エージェント側からは緩められない
03 Copilot CLIをWSL2に閉じ込める
起動時の引数
--no-sandboxを付けても無視される
--no-sandbox was ignored because an enterprise policy requires the sandbox.
作業フォルダの設定
エージェントが書き込める場所に緩める設定を書いても、効かない
フック
disableAllHooksでも作業フォルダのフックは動いた。ただしフックもサンドボックス内で動き、通信できない
別ターミナルでの人の操作は、対象外。運用ルールで扱う
遮断は、無害な結果に見えることがある
03 Copilot CLIをWSL2に閉じ込める
$ cat ~/outside/secret.txt
No such file or directory
ファイルは実在する。サンドボックスが存在ごと隠している
$ touch ~/probe ~/.copilot/probe
(作成できたと表示)
実際のホームには残っていない。仮のホームに書かれて捨てられる
防御としては問題ない。ただ、利用者が混乱しないよう「遮断されるとこう見える」を周知しておく
利用者へのお願いは「ランチャーから起動する」だけ
04 運用に落とす
$ copilot
Copilot CLIはランチャー(/opt/ai-env/launch-copilot.sh)から起動してください
$ /opt/ai-env/launch-copilot.sh
ランチャーがやること
許可リスト以外の環境変数を捨てる
Gitリポジトリを保護してから起動する
--sandboxと--disable-builtin-mcpsを付ける
直接起動はガード関数で案内に置き換える。設定し忘れる余地を作らない
Git:コミットはエージェント、Pushは人
04 運用に落とす
エージェント
コミット:できる
Push:できない
Could not resolve host: github.com
人(別ターミナル)
fine-grained PATでPushする
対象リポジトリだけ、Contentsの読み書きだけ、有効期限は短く。credential.helperのcacheでメモリに1時間だけ持つ
使わない:gh auth login、credential.helper store、SSH鍵。どれもディスクに残るため
仕込まれたフックは、人の操作で動く
04 運用に落とす
保護する前は、エージェントが置いたフックが、人のコミットをきっかけにWSL2内でも、Windows側のVS Codeからも実行された
対象 |
所有者と権限 |
|---|---|
|
root:worker 3775(作れるが消せない) |
|
root:root 0644(書き換えられない) |
|
root:root 0755(追加できない) |
自動で保護する
ランチャーの起動前と、1分ごとのタイマーで実行。既に怪しいフックや設定があれば警告する
消すときは、トークンを取り消してから
04 運用に落とす
削除は専用のスクリプト(Remove-AiDistro.ps1)で行う。
- 取り出す
ディストリ内のトークン。値は表示しない
- 取り消す
GitHubのRevoke API(202)
- 確かめる
そのトークンが401になるまで待つ
- 削除する
名前を再入力してから登録を解除
どこかで失敗したら、ディストリは消さずに止まる
先にwsl --unregisterで消すと、トークンを取り出せず手作業で取り消すしかない。手作業は必ず漏れる
VS Codeは、Windows側から開いて使う
04 運用に落とす
\\wsl.localhost経由で開くautomountを切っているので、WSL拡張では接続できない
- AI拡張は使わない
サンドボックスを通らずに、案件のファイルを扱えてしまう
- 制限モードで開く
エージェントが置いた
tasks.jsonなどが、Windows本体で自動実行されるのを防ぐ
「これで保証」ではなく、多層防御の一層
05 まとめ
残る制約 |
扱い |
|---|---|
管理設定が、契約形態や更新で効かなくなる可能性 |
構築時に(managed)の表示を確認する |
Copilot CLIは自動で更新される |
更新後に、同じ手順で再検証する |
別ターミナルでの人の操作 |
運用ルールで扱う |
Windows側からの参照( |
運用ルールで扱う |
意図的な迂回( |
サンドボックスは外れない。残りは運用ルール |
機密性に応じて環境を選び、
外部通信禁止の案件でもAIを使い続ける
05 まとめ
案件ごとの専用ディストリ + サンドボックス + 管理設定 + 運用ルール
ありがとうございました