CLAUDE_CODE_SUBPROCESS_ENV_SCRUBとは — 子プロセスから認証情報を消す環境変数
CLAUDE_CODE_SUBPROCESS_ENV_SCRUBはBash・hooks・MCPの子プロセスから認証情報を消す環境変数です。遮断範囲、Linux限定の挙動、sandbox設定との相互作用を扱います。
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB は、Claude Codeが起動する子プロセスから認証情報を消す環境変数です。対象はBashツール・hooks・MCPのstdioサーバーの3つです。1 を設定すると、AnthropicとクラウドプロバイダーのAPIキー、Claude Codeが認証情報と認識するその他の変数、パッケージレジストリのURLに埋め込まれた認証情報が取り除かれます。消えるのは子プロセス側だけです。親のClaudeプロセス自身はAPI呼び出しのために認証情報を保持し続けます。狙いは、プロンプトインジェクションがシェル展開経由で秘密情報を持ち出す経路を塞ぐことです。
CLAUDE_CODE_SUBPROCESS_ENV_SCRUBが遮断する範囲
遮断の対象は、Claude Codeが起動する3種類の子プロセスです。Claude Codeが実行するBashコマンド、hooksが起動するスクリプト、MCPのstdio方式で起動するサーバーが当たります。環境変数の一覧ページが挙げているのはこの3つだけで、対象の列挙にHTTP方式のMCPサーバーは含まれません。
消える情報の3種類
クラウドの認証情報
AnthropicとクラウドプロバイダーのAPIキー類です。
認証情報と認識される変数
上記以外でも、Claude Codeが認証情報として認識する変数が対象になります。
レジストリURL内のトークン
パッケージレジストリのURLに埋め込まれた認証情報です。
v2.1.251以降は、Claude Code自身の設定保存先を指す変数(CLAUDE_CONFIG_DIRなど)も消えます。設定ディレクトリを別の場所へ移している環境では、子プロセスがそのディレクトリを見つけられなくなります。子プロセスがこれらの変数を必要とするなら、スクラブは未設定のままにする必要があります。
値そのものが子プロセスの環境変数一覧から消えるので、printenvやenvを実行しても出てきません。
sandbox.credentialsのmaskと何が違うか
どちらも「子プロセスに認証情報の実値を見せない」点は同じです。違いは、通信が必要なツールを動かし続けられるかどうかにあります。
スクラブとmaskの住み分け
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB
Claude Codeが認識する認証情報を一括で遮断します。対象はBashツール・hooks・MCP stdioサーバーで、子プロセスは実値を受け取りません。差し替えの経路が無いので、環境変数の認証情報に頼るツールは、値が渡らず認証に失敗します。
sandbox.credentials(mode: "mask")
files/envVarsに列挙した変数・パスだけを個別に指定します。子プロセスにはセンチネル(偽の値)が見え、許可済みの通信先へ出るときだけプロキシが実値に差し替えます。効くのはサンドボックス化されたBashコマンドだけです。
サンドボックスだけでは、環境変数はClaude Codeから引き継がれ、中の秘密情報も含まれます。公式の対応表では、この項目にcredentialsとスクラブが並びます。
信頼していないhooksやMCPサーバーを動かすなら、「そもそも見せない」スクラブが向いています。認証情報で通信するツールを動かしながら守りたいなら、maskのほうが適しています。maskの設定は認証情報マスキングの設定ガイドに、サンドボックス全体の設計はClaude Codeのサンドボックス設計にまとめています。
設定方法
既定では無効です。何も設定しなければ、子プロセスは従来どおり親の環境変数を引き継ぎます。公式の記述は「1に設定する」で、シェルでの一時的な設定とsettings.jsonでの恒久的な設定のどちらも使えます。
export CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1
claudeチームやプロジェクト全体に配る場合は、.claude/settings.jsonのenvキーに書きます。止めるときは、この行を消すか、値を0にします。ターミナルで一時的に試した設定なら、unset CLAUDE_CODE_SUBPROCESS_ENV_SCRUBで元に戻ります。
真偽値の変数は一般則として、1・true・yes・onがオン、0・false・no・offがオフで、大文字小文字は問われません。設定ファイルのenvは変数を足せても消せないため、シェル側でexport済みの値を打ち消す場面では、行を消すだけでは足りません。envブロックの書き方全般はClaude Code設定ガイドにあります。
{
"env": {
"CLAUDE_CODE_SUBPROCESS_ENV_SCRUB": "1"
}
}有効にすると変わること
症状から探す: プロンプトが増えた、MCPが切れた
Claude Code本体の認証は変わらず、変わるのは子プロセスの側です。有効化の直後に起きやすい変化を、症状の側からたどります。
有効化後に困ったときの切り分け
- 1
サンドボックスなのにプロンプトが増えた
sandbox.autoAllowBashIfSandboxedの自動許可が止まっています。サンドボックスそのものはオフになりません。設定リファレンスは「CLAUDE_CODE_SUBPROCESS_ENV_SCRUBが自動許可をオフにする」と明記しています。サンドボックス化されたBashが通常の権限フローに戻るので、allowルールか権限モードで判定されます。 - 2
`ps`や`kill`が効かない(Linux)
Linuxでスクラブを設定すると、Bashの子プロセスが独立したPID namespaceで動くためです。ホスト側のプロセスは見えず、シグナルも送れません。
- 3
環境変数の認証情報に頼るツールが失敗する
このツールだけは、スクラブでなくmaskで守る構成に分けます。
- 4
MCPサーバーが起動時に切れた
stdioサーバーはスクラブの対象です。環境変数の認証情報に依存するサーバーは、起動後に認証で失敗することがあります。
自動許可が止まる仕組み
sandbox.autoAllowBashIfSandboxedは既定がtrueで、サンドボックス化されたBashを権限プロンプトなしで実行する設定です。スクラブを有効にすると、この自動許可だけが止まります。denyルールやBash(git push *)のような内容限定のaskルールは、どちらの状態でも変わらず適用されます。権限ルールの評価は変わりません。この設定の単独の解説はautoAllowBashIfSandboxedの記事にあります。
Linuxでは!シェルモードもサンドボックスに入る
入力の先頭に!を付けるシェルモードのコマンドは、ユーザーが直接打ちます。strict sandbox mode(allowUnsandboxedCommands: false)でも、サンドボックスの外で動くのが通常です。例外が2つあります。バックグラウンドセッションと、スクラブを設定したLinuxセッションです。後者では、シェルモードを含むすべてのコマンドがサンドボックス化されます。環境変数の除去が対象とするのはBashツール・hooks・MCP stdioサーバーの3種で、!はこの列挙に含まれません。
この挙動はv2.1.260で変わりました。v2.1.260より前は、strict sandbox modeがどのセッションでもシェルモードを含めてサンドボックス化していました。allowUnsandboxedCommandsの設定はサンドボックス外実行の記事にまとめています。
スクラブはファイルシステム隔離も固定する
スクラブを設定すると、filesystem.disabledはどの設定ソースからのものも無視されます。管理設定(managed settings)も例外ではありません。ファイルシステム隔離はオンのまま保たれます。通常は、ユーザー設定・管理設定・--settingsだけがfilesystem.disabledを設定できます。スクラブがあるとその経路も塞がれます。なお、filesystem.disabledでファイルシステム隔離を切った場合も、credentials.envVarsのdenyとmaskは有効なままです。環境変数の除去はファイルシステム層とは独立しているためです。設定の読まれ方はfilesystem.disabledの記事で扱っています。
hooksが引き継ぐ環境変数
hookプロセスは親の環境変数を引き継ぎますが、例外が2つあります。常時除外されるOTEL_*のエクスポーター変数と、スクラブが1のときに追加で取り除かれる認証情報系の変数です。OTEL_*はBashツール・hooks・MCPサーバー・言語サーバーのすべてに渡されません。OpenTelemetryで計装したアプリをBash経由で動かしても、Claude Codeのエクスポーター設定を継承しないということです。スクラブが無効なら、認証情報系の変数もhookプロセスに引き継がれます。hooksスクリプトから外部サービスへ通知する構成では、有効化後に認証情報が渡らなくなる点に注意が要ります。
CLAUDE_CODE_SCRIPT_CAPSで呼び出し回数まで絞る
CLAUDE_CODE_SCRIPT_CAPSは、スクラブが設定されているときだけ効く、セッション単位の追加防御です。JSONオブジェクトで、キーにコマンド文字列の部分一致、値に呼び出し回数の上限を指定します。
{
"env": {
"CLAUDE_CODE_SUBPROCESS_ENV_SCRUB": "1",
"CLAUDE_CODE_SCRIPT_CAPS": "{\"deploy.sh\": 2}"
}
}この例では、deploy.shを含むコマンドがセッション中に2回までしか実行できなくなります。マッチングは部分一致です。./scripts/deploy.sh $(evil)のようにシェル展開を仕込んでも、上限にカウントされます。ただしxargsやfind -execによるランタイムの多重起動は検出されません。多層防御の1つで、実行回数を保証する機能ではありません。
claude-code-actionでの自動設定
GitHub Actionsのclaude-code-actionは、allowed_non_write_usersを設定しているときにこの変数を自動で有効にします。書き込み権限を持たないユーザーのイベントを許可するための設定で、公式のGitHub Actionsページでは、自前のgithub_tokenも渡すよう求めています。
hooksやMCPサーバーの子プロセスに認証情報が渡らないよう、CI側で先に塞いでくれる形です。自前のワークフローで似た構成を組むなら、明示的に設定しておけば同じ防御が働きます。
まとめ
有効化の前に、接続中のMCPサーバーとhooksがどの変数を必要としているかを洗い出しておくと、失敗の切り分けが早く済みます。設定ファイルに書いた場合の止め方は、行を消すか0にするかの2通りです。