ブログ一覧

bypass の Claude Code に作業ディレクトリの外へ書かせない3つの設定

Claude Code 2.1.314 で、Write・Edit・NotebookEdit が作業ディレクトリの外に書くのを、どの権限モードでも拒否する設定 permissions.blockWritesOutsideWorkingDirectories が入りました。作業ディレクトリは Claude Code を起動したディレクトリと --add-dir などで足したディレクトリのことです。確認をすべて飛ばす bypass モードでも効くと書かれていたので、この設定1つで外に書かれなくなるのか確かめてみました。

この設定を true にすると、bypass でも Write・Edit・NotebookEdit は作業ディレクトリの外に書けなくなり、作業ディレクトリの中に置いたシンボリックリンク越しの書き込みも、エージェントが Edit で設定を false に書き換えるのも止まりました。ただ、CHANGELOG に書かれているのもファイル編集ツールだけで、対象に入っていない Bash の > や cp は外に書けました。Bash の書き込みまで止めるには、Bash を OS の機能で隔離するサンドボックスの sandbox.enabled と sandbox.allowUnsandboxedCommands: false を一緒に入れます。

bypass で設定を足すごとに外に書けた書き込み方が減り、3つの設定を入れると4種類とも止まった

ファイル編集ツールは bypass でも外に書けなくなる

試したのは Linux の Claude Code 2.1.316 です。作業ディレクトリとその外のディレクトリを用意して、外への書き込みを1つずつ頼み、外のディレクトリのファイルの有無と中身で結果を見ました。

設定は .claude/settings.json に次の3行を書くだけです。

{
  "permissions": { "blockWritesOutsideWorkingDirectories": true }
}

bypass で設定なしだと、次の4つのすべてで外のファイルが作られたり書き換わったりしました。

  • Write での新規作成
  • Edit での既存ファイルの書き換え
  • NotebookEdit での .ipynb のセルの書き換え
  • 作業ディレクトリの中に置いた「外を指すシンボリックリンク」越しの Write

設定を入れると同じ4つがすべて拒否され、外のファイルは変わりませんでした。返ってきたエラーメッセージは次のとおりです。

/tmp/…/outside/write.txt is outside /tmp/…/ws; the permissions.blockWritesOutsideWorkingDirectories setting blocks writes outside the working directories. Ask the user to add the directory with /add-dir, or to remove that setting.

シンボリックリンク越しの Write は、リンクの先の場所が外にあるとして拒否されていました。auto モードと、permissions.allow で Write・Edit・NotebookEdit を許可した default モードでも結果は同じで、設定なしでは外に書け、設定ありでは4つとも拒否されました。試した3つのモードでは、許可ルールで通していても設定が優先されました。

エージェントが設定を自分で外せないかも見ました。この設定を入れた bypass で .claude/settings.json の true を false にする Edit を頼むと、設定ファイルを書けば制限を外せるのでそこへの書き込みは止める、という意味のメッセージで断られ、作業ディレクトリの中でも Edit で .claude/settings.json を書き換えられませんでした。

ただ、サンドボックスが無ければ bypass では Bash で .claude/settings.local.json に {"permissions":{"blockWritesOutsideWorkingDirectories":false}} を書けました。それでも外への Write は、同じセッションでも次に起動したセッションでも拒否されたままで、どこかの設定ファイルに true があれば、別のファイルの false では外れないようです。

これは公式の文書には書かれておらず、私が試して分かったことです。読み込みを禁じる側の設定(blockReadsOutsideWorkingDirectories)には、どこか1つの設定ファイルで true にすれば、ほかのファイルの false では外れないと書いてありますが、書き込み側の設定はまだ設定の一覧に載っていません。

Bash の書き込みはサンドボックスで止める

設定を入れても、Bash の次の3つは bypass でも auto でも Bash を許可ルールに入れた default でも通り、外にファイルができました。

  • echo B > 外/…
  • cp 中のファイル 外/…
  • python3 -c "open('外/…','w').write('P')"

bypass で設定を入れて Write と Bash を続けて頼んだときの画面が次です。Write は拒否されました。モデルはそのエラーメッセージを読み、Bash でも同じ所に書くことになるからと言って自分で手を止めました。ただ、続けて頼むと Bash の echo B > ../outside/b.txt は通り、b.txt ができました。Bash を止めたのはモデルの判断で設定ではなく、頼み方しだいで Bash は外に書きます。

bypass の Claude Code で、Write は設定に拒否され、Bash の echo は外に書けた画面

サンドボックスは、Claude Code が Bash のコマンドを OS の機能で隔離し、書ける場所を、作業ディレクトリ(--add-dir で足した物を含む)とユーザーごとの一時ディレクトリに限る機能です。一時ディレクトリは $TMPDIR が指す場所で、/tmp 全体ではありません。Linux ではプロセスを隔離するツールの bubblewrap と、通信を中継するツールの socat の2つのパッケージが要り、Ubuntu や Debian なら次で入りました。

apt-get install bubblewrap socat

.claude/settings.json に "sandbox": { "enabled": true } を足すと、Bash を許可した default でも bypass でも、Bash の3つは OS 側で拒否されました。Write・Edit・NotebookEdit とリンク越しの Write も拒否されたままです。

/bin/bash: line 1: /tmp/…/outside/bash-redirect.txt: Read-only file system
cp: cannot create regular file '/tmp/…/outside/bash-cp.txt': Read-only file system
OSError: [Errno 30] Read-only file system: '/tmp/…/outside/bash-python.txt'

サンドボックスの中の Bash は、作業ディレクトリの中でも設定ファイルを書けません。bypass とサンドボックスで、Bash に echo '{"sandbox":{"enabled":false}}' > .claude/settings.local.json を頼むと「Permission denied」で書けず、同じ .claude/ の中の普通のファイルは書けました。ユーザーの設定ファイルへの書き込みも「Read-only file system」になり、エージェントがサンドボックスを自分で切ることはできませんでした。

bypass と auto ではサンドボックスの外での実行も禁止する

Bash ツールには、モデルがコマンドごとにサンドボックスの外で走らせるオプション(dangerouslyDisableSandbox)があります。設定とサンドボックスを入れた状態で、このオプションを付けた echo E > 外/escape.txt を頼むと、bypass と auto では確認なしで走り、外に escape.txt ができました。default では、Bash を許可していてもいなくても、同じオプションは「Run outside of the sandbox」の確認に回りました。

サンドボックスの設定を "sandbox": { "enabled": true, "allowUnsandboxedCommands": false } にすると、bypass でも auto でもこのオプションは無視され、コマンドはサンドボックスの中で走って「Read-only file system」になりました。

bypass で Bash の書き込みまで止めるために試した設定は次のとおりです。

{
  "permissions": { "blockWritesOutsideWorkingDirectories": true },
  "sandbox": { "enabled": true, "allowUnsandboxedCommands": false }
}

この組み合わせで、図の4種類はどれも外に書けず、作業ディレクトリの中への Write は通りました。

試したのは Linux だけで、次のことは試していません。

  1. macOS と Windows
  2. 組織で配る managed settings に置いたとき
  3. acceptEdits で、許可ルールで通したファイル編集ツールにこの設定が効くか
  4. acceptEdits で dangerouslyDisableSandbox を付けたとき
  5. MCP やプラグインのツールによる書き込み
  6. サンドボックスの excludedCommands に入れたコマンド

6 は試していませんが、公式の文書によると excludedCommands に入れたコマンドはサンドボックスの外で走ります。

Bash を確認なしで走らせるならサンドボックスも入れる

blockWritesOutsideWorkingDirectories 1つで、試した bypass・auto・default では許可ルールで Write や Edit を通していても外には書かれず、シンボリックリンク越しも、エージェントが Edit で設定を書き換えて外すことも止まりました。そのうえで入れる設定は、Bash が確認なしで外に書くかどうかで変わります。default と acceptEdits で Bash を許可ルールに入れていなければ、外へのリダイレクトは設定が無くても「Output redirection to '…' needs approval」の確認に回りました。

  1. default と acceptEdits で Bash を許可ルールに入れていない: blockWritesOutsideWorkingDirectories だけ。default では許可ルールで通したファイル編集ツールの書き込みまで止められる。acceptEdits でのファイル編集ツールへの効き方は試していない
  2. auto、Bash を許可ルールに入れた default: Bash が確認なしで外に書くので sandbox.enabled も要る。auto では dangerouslyDisableSandbox のオプションも確認なしで通ったので allowUnsandboxedCommands: false も要る
  3. bypass: 3つとも要る

全部のプロジェクトに効かせたいなら、ユーザーの設定(~/.claude/settings.json)に1回書けば済みます。3つの設定をユーザーの設定に置いても、プロジェクトの .claude/settings.json に置いたときと同じく、Write は拒否され、Bash は「Read-only file system」になりました。

サンドボックスを入れたときに普段のビルドやテストが動くかは確かめていないので、入れる前に自分のビルドやテストで確かめる必要があります。

この記事をシェア