0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Copilot CLIのサンドボックス、Linuxはbwrapが無いと動かない

0
Posted at

TL;DR

  • GitHub Copilot CLI v1.0.79(2026-08-10)で、ワークスペース内の PATH 上のツールディレクトリ(.venv/binnode_modules/.bin・リポジトリ内 GOPATH)がワークスペースの一部を read-only にしてしまう挙動が修正されました
  • Linux のサンドボックスは bubblewrap(bwrap)0.5.0 以上が前提です。素の Ubuntu コンテナには入っておらず、無いまま有効化すると サンドボックス対象のシェルコマンドとサーバーが全部失敗 します
  • サンドボックスの認証設定キーが sandbox.gitAuth / sandbox.ghAuth から sandbox.auth.git / sandbox.auth.gh にリネームされました
  • 「ネストした read-only パスが書き込み可能を継承してしまう/しない」は bind の適用順で決まります。bubblewrap で同じ構図を再現したところ、順序を入れ替えるだけで node_modules/.bin への書き込み可否が反転しました

はじめに

対象読者は、GitHub Copilot CLI を Linux 上で使っていて、実験的機能のコマンドサンドボックスを有効にしたい(あるいは有効にしたら動かなくなった)開発者です。

Copilot CLI v1.0.79 の変更点として「サンドボックスでツールディレクトリを書き込み可能に保てるようになった」が挙がっています。一見すると細かいバグ修正ですが、実際に踏むと npm installcargo build がサンドボックス内だけ失敗するという分かりにくい形で表面化します。

今回は v1.0.79 を実際に入れて、ヘルプに出てくるポリシー面を確認し、Linux 側のホスト要件を確かめ、read-only の入れ子がどう効くのかを bubblewrap で再現しました。

v1.0.79 で変わったこと

公式の changelog(github/copilot-cli の changelog.md)には、1.0.79(2026-08-10)として次の記述があります。

A tool directory inside your workspace that is on PATH (.venv/bin, node_modules/.bin, an in-repo GOPATH) no longer turns that part of the workspace read-only

あわせて macOS 側では「書き込み可能なパスの内側にネストした read-only パスが、広い方の書き込み権限を継承せず read-only のままになる」修正が入っています。

つまり 「ワークスペースは書けるが、その内側のツールディレクトリは読み取り専用」という入れ子の扱い をまとめて整理したリリースです。

同じリリースには、設定キーの破壊的変更が 2 つ含まれています。どちらも 移行処理が無い ので、既存の settings.json を持ち込むときに効いてきます。

旧キー 新キー 旧キーの扱い
sandbox.gitAuth / sandbox.ghAuth sandbox.auth.git / sandbox.auth.gh 設定ファイル内では無視される。SDK リクエストが送った場合は invalid として拒否される
sandbox.allowDevToolCaches sandbox.allowDevToolAccess 読まれず、黙って無視される

changelog は前者について「There is no migration」と明記し、後者を BREAKING として扱っています。

BREAKING: the sandbox setting allowDevToolCaches is renamed allowDevToolAccess (...) The old key is no longer read and is ignored silently, so an existing false opt-out reverts to the default (on).

後者はとくに注意が必要です。「開発ツールの場所への自動許可を切る」ために allowDevToolCaches: false を書いていた場合、v1.0.79 に上げると その opt-out が消えて既定のオンに戻ります。切っていたつもりの許可が復活する方向の変更なので、設定ファイルを配布している環境では上げる前に置換しておく必要があります。

実際に入れて確かめる

まず npm でインストールします。

$ npm install -g @github/copilot@1.0.79
added 3 packages in 15s

$ copilot --version
GitHub Copilot CLI 1.0.79.
Run 'copilot update' to check for updates.

サンドボックスはトップレベルのサブコマンドではなく、ヘルプトピックとして提供されています。copilot --help の Help Topics 側に並んでいます。

$ copilot --help | sed -n '/Help Topics/,/^$/p'
Help Topics:
  billing      AI credit usage
  commands     Interactive Mode Commands
  config       Configuration Settings
  environment  Environment Variables
  limits       Session Limits Controls
  logging      Logging
  monitoring   Monitoring with OpenTelemetry
  permissions  Permissions
  providers    Custom Model Providers (BYOK)
  sandbox      Command Sandboxing

copilot sandbox --help と打ってもトップレベルヘルプが返ってくるだけなので、copilot help sandbox で開くのが正解でした。ここで実装の前提がはっきり書かれています。

前提1: Linux は bwrap が必須

ヘルプの Supported hosts 節に、バックエンドとホスト要件が明記されています。

macOS    Uses the MXC Seatbelt backend (`sandbox-exec`).
Linux    Uses the MXC bubblewrap backend; requires `bwrap` 0.5.0+ on PATH.
Windows  Uses the MXC ProcessContainer backend, which targets Windows 11.

サンドボックスは Microsoft Execution Containers(MXC)という抽象レイヤ越しに、OS ごとのネイティブな隔離機構を使う設計です。Linux では bubblewrap がそのバックエンドになります。

検証に使った Ubuntu ベースのコンテナには入っていませんでした。

$ bwrap --version
bash: bwrap: command not found

この状態でサンドボックスが有効になっていると、ヘルプにはこう書かれています。

every sandboxed shell command and every sandboxed MCP/LSP server fails

起動時に警告は出るものの、失敗するのはコマンド実行時です。CI コンテナや開発用イメージで sandbox.enabled: true を設定ファイルごと配って回ると、この踏み方をします。導入は 1 行で済みます。

$ apt-get install -y bubblewrap
Setting up bubblewrap (0.9.0-1ubuntu0.1) ...

$ bwrap --version
bubblewrap 0.9.0

要件は 0.5.0 以上なので、Ubuntu 24.04 系の 0.9.0 で満たせます。

前提2: experimental を有効にしないとコマンドが生えない

もう一点、ヘルプの冒頭に書かれている制約があります。

The /sandbox command (and its enable/disable subcommands) is only registered when experimental features are on; otherwise it returns "Unknown command".

つまり /sandbox が「Unknown command」で返ってきたときに疑うべきはタイポではなく、experimental が off であることです。--experimental フラグか /settings experimental on で有効化します。

前提3: classic PAT では認証できない

非対話モードで動作確認しようとしたところ、認証ではじかれました。

$ copilot -p "Reply with exactly: OK" --allow-all-tools --silent
Error: Classic Personal Access Tokens (ghp_) are not supported by Copilot.

The GH_TOKEN environment variable contains a classic PAT.
Please use a Fine-Grained Personal Access Token or another authentication method.

環境に GH_TOKEN が入っている CI やクラウド実行環境では、それが classic PAT だと Copilot CLI 側で即エラーになります。fine-grained PAT に差し替えるか、GH_TOKEN を unset して /login を使う必要があります。

なお GitHub Docs のトラブルシューティングでは、classic PAT は「silently ignored(黙って無視され、トークン未設定として振る舞う)」と説明されています。今回の v1.0.79・非対話モード(-p)では上記のとおり明示的なエラーが返りました。黙って無視される挙動を想定していると原因究明が長引くので、エラーで止まってくれる方はむしろ親切です。この都合で、今回はエージェントループを回した実測までは到達できていません(後述の再現実験はバックエンドの bubblewrap 単体で行っています)。

ポリシーの構造を読む

copilot help sandbox の Configuration 節には、settings.jsonsandbox キー配下の設定が 11 項目載っています。

設定キー 役割
enabled コマンドサンドボックスの有効・無効
addCurrentWorkingDirectory カレントディレクトリに読み書きを付与(有効化時は既定でオン)
allowDevToolAccess ビルドが必要とする開発ツールの場所を自動許可(既定オン)
allowBypass コマンド単位でサンドボックスを外す逃げ道を許可
auth.git / auth.gh git・gh の認証情報をサンドボックス内へ注入
sandboxMcpServers / sandboxLspServers ローカル(stdio)の MCP・LSP サーバーもサンドボックス内で起動するか
userPolicy.filesystem.readwritePaths / readonlyPaths / deniedPaths 追加で読み書き・読み取り専用・拒否するパス
userPolicy.filesystem.clearPolicyOnExit セッション終了時にファイルシステムポリシーを破棄
userPolicy.network.allowOutbound 外向きネットワーク接続の可否
userPolicy.network.allowLocalNetwork ローカルネットワークへの接続可否
userPolicy.seatbelt.keychainAccess macOS のキーチェーンへのアクセス可否

旧キー名の gitAuth / ghAuth はヘルプ本文から消えており、grep してもヒットしません。

$ copilot help sandbox | grep -c "gitAuth\|ghAuth"
0

既存の settings.json を持ち込む場合、リネーム前のキーを書いたままだと認証情報の注入設定が意図どおりに効かない可能性があります。v1.0.79 に上げるタイミングで書き換えておくのが安全です。

なぜ PATH のツールディレクトリが問題になるのか

今回の修正を理解する鍵は、ファイルシステムの既定ポリシーにあります。ヘルプにはこう書かれています。

By default access is limited to your working directory, PATH directories, the temp directory, and your user profile.

ワークスペースPATH に入っているディレクトリ が、それぞれ別々に許可対象として並びます。Node.js プロジェクトで node_modules/.bin を PATH に足していると、この 2 つが入れ子になります。

ワークスペース全体に read/write を与え、そのサブディレクトリに read-only を与える。この 2 つの規則が衝突したとき、どちらが勝つかは実装(と適用順)次第です。v1.0.79 は、この衝突を「ワークスペース内の PATH ツールディレクトリはワークスペースの書き込み権を潰さない」方向に、macOS では「明示した read-only は書き込み権を継承しない」方向に揃えました。

bubblewrap で入れ子の挙動を再現する

Linux バックエンドの bubblewrap 単体でも、同じ構図を再現できます。ワークスペースを用意します。

WS=/tmp/copilot-sandbox-demo/work
mkdir -p "$WS/node_modules/.bin" "$WS/src"
echo "console.log('hi')" > "$WS/src/index.js"
printf '#!/bin/sh\necho tool\n' > "$WS/node_modules/.bin/mytool"
chmod +x "$WS/node_modules/.bin/mytool"

サンドボックス内で 3 箇所に書き込みを試すプローブを用意します。

#!/bin/sh
WS=/tmp/copilot-sandbox-demo/work
for p in "$WS/src/new.txt" "$WS/node_modules/pkg.txt" "$WS/node_modules/.bin/new-bin"; do
  if echo x > "$p" 2>/dev/null; then echo "WRITE OK   ${p#$WS}"; else echo "WRITE DENY ${p#$WS}"; fi
done

ケースA として、ワークスペースを read/write でバインドした あと.bin を read-only でバインドします。

$ bwrap --ro-bind / / \
    --bind $WS $WS \
    --ro-bind $WS/node_modules/.bin $WS/node_modules/.bin \
    --proc /proc --dev /dev --chdir $WS /bin/sh probe.sh
WRITE OK   /src/new.txt
WRITE OK   /node_modules/pkg.txt
WRITE DENY /node_modules/.bin/new-bin

ケースB として、順序だけを入れ替えます。.bin を read-only でバインドした あと にワークスペースを read/write でバインドします。

$ bwrap --ro-bind / / \
    --ro-bind $WS/node_modules/.bin $WS/node_modules/.bin \
    --bind $WS $WS \
    --proc /proc --dev /dev --chdir $WS /bin/sh probe.sh
WRITE OK   /src/new.txt
WRITE OK   /node_modules/pkg.txt
WRITE OK   /node_modules/.bin/new-bin

同じ 2 つの規則で、順序を入れ替えただけで node_modules/.bin への書き込み可否が反転しました。ケースAでは read-only の指定が後から被さって .bin だけが書けなくなり、ケースBでは後から張った read/write のマウントが read-only 指定を覆い隠します。

なお、この実験は Copilot CLI 内部の MXC が発行するポリシーそのものではなく、Linux バックエンドとして使われている bubblewrap の入れ子マウントの挙動を確かめたものです。「入れ子の順序で結果が反転する」という性質が、changelog の 2 つの修正(ツールディレクトリが workspace を read-only にする/ネストした read-only が write を継承する)が同時に出てきた背景にあると読めます。

一次所見: 運用に落とすときの注意

実際に v1.0.79 を触って感じたのは、サンドボックスの難所が「ポリシーの表現力」ではなく ホスト側の前提と、ポリシーの重なり方 に寄っている点です。

  • ホスト要件は起動時に落ちない: bwrap が無くても Copilot CLI 自体は起動します。失敗するのはサンドボックス対象のコマンドを実行した瞬間なので、原因がサンドボックスだと気づくまでに時間を取られます。イメージのビルド時点で bwrap --version を通しておくのが確実です
  • allowDevToolAccess は既定オン: ~/.npmrc~/.m2/settings.xml のようなレジストリ設定は既定で読めます。そこにトークンを書いているなら、サンドボックス内のコマンドから読めるという前提で運用する必要があります。嫌なら明示的に切って readonlyPaths / readwritePaths で組み立て直す設計になっています
  • 設定キーのリネームは静かに効く: gitAuthauth.gitallowDevToolCachesallowDevToolAccess のどちらも移行処理がありません。動かなくなるというより「注入されているつもりが注入されていない」「切ったつもりの許可が既定のオンに戻っている」形で表面化します。バージョンを上げるときは settings.json を必ず見直します
  • 実効ポリシーを見るコマンドが増えた: v1.0.79 では /sandbox policy で、実際に効いているパス・拒否・ネットワーク許可を確認できるようになりました。設定を書き換えたら、意図どおりのポリシーになっているかをここで突き合わせるのが早道です

参考

関連記事

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?