認証情報とワイヤ境界

エージェント型コーディングセッションには認証情報が必要です。Claude と通信するための Anthropic キー、プッシュするための GitHub トークン、デプロイするための AWS キーなどです。同時にこの環境は、任意のコードを実行し、任意のパッケージをインストールし、自らが書いたわけではないファイルの指示に従います。そのような環境に本物のシークレットを渡すことこそ、キーが窃取マルウェアの受信箱に流れ着く原因になります。

Bromure Agentic Coding はこの緊張関係をワイヤ境界によって解決します。VM 内のエージェントが目にするのは、常に偽のプレースホルダートークンだけです。本物の認証情報は macOS ホスト上に暗号化されて保管され、ホスト側の MITM プロキシによって、可能な限り最後の瞬間に — リクエストが VM を離れた後、かつその認証情報が属するホスト宛てである場合に限って — ワイヤ上で差し替えられます。VM 内のファイル、環境変数、プロセスのいずれも、本物の API キー、OAuth トークン、AWS シークレット、SSH 秘密鍵を保持することは決してありません。

この章では、まず仕組みを端から端まで説明し、続いてエージェントのサインイン方法、サポートされる各認証情報の種類とそのライフサイクル、利用ごとの承認の仕組み、侵害検出器、傍受下では動かないホストのための回避策、そして境界を自分で確かめる方法を順に説明します。

認証情報はマシンごとに設定します。マシンは、設定エディタではいまも ワークスペース と呼ばれています。どちらの言葉も、同じ VM とその設定を指します。

メモ: この章では概念と実行時の動作を扱います。設定ペインのフィールドごとのリファレンスは、設定 → 認証情報を参照してください。エージェントの API キーとサブスクリプションは、もうそのペインでは設定しません。環境設定 › モデル にあります(モデルとプロバイダーを参照)。

ワイヤ境界の概要

このモデルは 3 つの原則で定義されます。

  1. VM 内は偽物。 設定したすべての認証情報は、VM 内では構造を保持した偽物に置き換えられます。偽物はバリデーターが期待する形状を保ちます — Anthropic の偽物は sk-ant-api03-brm- で始まり、GitHub の偽物は ghp_ に 36 文字が続きます — そのため claude、gh、doctl のようなツールは問題なくそれらを受け入れます。
  2. 本物はワイヤ上のみ。 VM が行うすべての HTTPS リクエストはホストプロキシへトンネリングされ、プロキシがそれを復号し、偽物を本物の値に差し替え、上流へ向けて再暗号化します。差し替えは、その認証情報が発行された宛先ホストに限定されます。
  3. フェイルクローズ。 何かがプロキシを迂回した場合、そのリクエストは偽物しか運ばず、上流での認証は失敗します。本物のシークレットが偶発的に漏洩する経路は存在しません。

偽物は決定論的です。各偽物は、本物の値とインストールごとの 32 バイトのソルトから HKDF-SHA256 によって導出されます。同じ本物のキーは、あなたの Mac 上で常に同じ偽物にマッピングされるため、キーをフィンガープリントするクライアント(たとえば Claude Code はキーのハッシュをキャッシュします)は、セッションをまたいで認証情報が「ローテーション」するのを目にすることはありません。

認証情報VM 内での偽物の形状
Anthropic API キーsk-ant-api03-brm-…
OpenAI API キーsk-brm-…
xAI API キーxai-brm-…
Moonshot(Kimi)の API キーsk-kimi-brm-…
Claude Code が使う OpenRouter のキーsk-or-v1-brm-…
Amazon Bedrock の API キーbedrock-brm-…
GitHub トークンghp_ + 36 文字(合計 40)
GitLab トークンglpat- + 20 文字
DigitalOcean PATdop_v1_ + 16 進(合計 64 文字)
Linear API キーlin_api_ + 40 文字(合計 48)
Twilio の認証トークン/API キーのシークレットbrm-twilio-…(32 文字以上)
MCP ベアラートークンbrm-mcp_…
Docker レジストリパスワードbrm-docker-…(最低 40 文字)
Kubernetes ベアラートークンbrm-k8s-…
データベースシークレットbrm-db-…(最低 32 文字)
汎用の手動トークンbrm_…

この境界にオン/オフのスイッチはありません。プロキシは VM の唯一の egress 経路であり、差し替えは単にこのアプリにおける認証情報の動作方式そのものです。

差し替えが端から端までどう機能するか

認証されたリクエスト 1 件の完全な往復は次のとおりです。

  1. セッションの起動――トークンプラン。 マシンの VM が起動すると、アプリはマシンごとのトークンプランを作り、本物の認証情報それぞれに、そこから派生したダミーを対応させます。ダミーは VM に書き込まれます。環境変数(ANTHROPIC_API_KEY、GH_TOKEN、LINEAR_API_KEY、…)と設定ファイル(~/.git-credentials、~/.docker/config.json、~/.kube/config、~/.aws/config、~/.config/doctl/config.yaml、MCP の設定)です。本物の値はプロキシのメモリ上の差し替えマップに読み込まれ、それぞれが属する宛先ホストに結び付けられます。
  2. リクエストが VM を離れる。 ゲストの HTTPS トラフィックは、virtio ソケット(vsock ポート 8443)を経由してホストプロキシへトンネリングされます。VM にはネットワークへの他の経路はありません。
  3. TLS 終端。 プロキシは、偽造されたホストごとのリーフ証明書 — CN および SAN として宛先ホスト名、ホストごとの EC キー — を提示し、これは Bromure Agentic Coding Root CA によって署名されています。この CA の公開証明書は起動時に VM のトラストストアにインストールされているため、ゲストの TLS クライアントは接続を受け入れ、プロキシは平文のリクエストを読み取ることができます。
  4. 差し替え。 プロキシはリクエスト(ヘッダー、およびオプトインした認証情報の種類についてはボディ)に現れるすべての偽トークンを探し、宛先ホストがその認証情報のスコープと一致すれば、それを本物の値に置き換えます。
  5. 上流への再暗号化。 書き換えられたリクエストは、Apple の URLSession、すなわち macOS 自身の TLS スタックを介して本物の宛先へ再送出され、それが上流サーバーの本物の証明書を検証します。レスポンスはトンネルを通ってゲストへストリーミングで戻ります。

宛先が偽物のスコープと一致しない場合、偽物はそのまま送出され(そして上流の認証に失敗し)— あるいは、その不一致が持ち出しのように見える場合、リクエストは即座にブロックされます(以下の侵害検出器を参照)。

Bromure Agentic Coding Root CA

CA はインストールごとに存在し、~/Library/Application Support/BromureAC/ca/(cert.pem とモード 0600 の key.pem)に置かれています。そのサブジェクトは「Bromure Agentic Coding Root CA」、組織は「Bromure」です。知っておくと役立つ特性は次のとおりです。

  • CA の有効期間は 10 年です。偽造されたホストごとのリーフ証明書は有効期間 1 年で、24 時間さかのぼって日付が設定されているため、サスペンド/レジューム中に時刻がずれたゲストでも受け入れられます。リーフはアプリのプロセスが生きている間、ホストごとにキャッシュされます。
  • 公開証明書は起動時にすべての VM のトラストストアにインストールされます(メタ共有を通じて配信され、update-ca-certificates で適用されます)。それはあなたのマシンを離れることはなく、あなたの VM 以外の何ものにも信頼されません。
  • CA をローテーションするには、アプリを終了して ca/ ディレクトリを削除します。次回の起動時に新しい CA が発行され、各 VM は次回の起動時に新しい公開証明書を取り込みます。ローテーションはそれ以外の何も無効化しません — ワークスペースのシークレットと profile.json のメタデータはそのまま保たれます。

ホストスコーピング

各差し替えエントリはホストスコープに束縛されます。マッチングは完全一致またはサブドメインで、大文字小文字を区別せず、部分文字列では決してマッチしません。openai.com にスコープされた認証情報は api.openai.com にはマッチしますが openai.com.evil.example にはマッチしません — 見た目のよく似たホストが、プロキシを騙して本物のキーでリクエストを飾らせることはできません。手動トークンのルールは、意図的に空白のホストフィルターを使うことができ、それは「任意のホストで注入する」ことを意味します。それはエントリごとにあなたが行う明示的な選択です(汎用 API キーを参照)。

構造としてのフェイルクローズ

この設計は、秘匿性のためにプロキシが不可避であることに決して依存しません — シークレットがそこに存在しないことに依存します。

  • 何らかの形でプロキシをスキップしたリクエストは偽トークンを運びます。上流の API はそれを拒否します。
  • VM 内で署名された AWS リクエストは偽のシークレットキーで署名されます。それらが AWS に直接到達した場合、InvalidSignatureException で失敗します(以下の AWS を参照)。
  • SSH 秘密鍵のバイト列は VM 内にはまったく存在しません。境界を越えるのは署名だけです。

ワークスペースエディタで認証情報を管理する

サービスの認証情報――git トークン、クラウドのキー、レジストリ、データベース、SSH キー――はマシンごとに設定します。マシンの設定を開き(マシンメニューの 設定…、またはセッションのメニューの 「マシン」の設定…)、サイドバーの セキュリティ の下にある 資格情報 を選びます。

Web app ワークスペースのエディタの資格情報ペイン:Git のアイデンティティの名前とメールのフィールド、「資格情報はまだありません」という空の状態、そして「認証情報を追加」と「env ファイルを読み込む…」のボタン。

ペインの先頭には Git のアイデンティティ(VM 内の ~/.gitconfig に書き込まれる名前とメールアドレス。両方空のままにすると git の既定値が使われます――プレースホルダは例にすぎず、認証情報ではありません)があり、その下に、設定済みの認証情報だけがカテゴリ見出し(Agents、Git、Cloud、Databases、SSH、Other)ごとに並びます。何も設定していなければ、ペインには 資格情報はまだありません と表示されます。下部には 2 つのボタンがあります。認証情報を追加 は認証情報の種類――Git token、SSH key、AWS credentials、DigitalOcean token、Linear API key、Twilio API key、Kubernetes、Container registry、Database、Other API key――を選ぶピッカーを開き、env ファイルを読み込む… は .env や ~/.bashrc からまとめて取り込みます。保存 をクリックすると、次にセッションを起動したときにダミーが VM に書き込まれ、本物の値がプロキシに読み込まれます。

エージェントの API キー(Anthropic、OpenAI、xAI、Moonshot などのモデルプロバイダー)はこのピッカーにはありません。次に説明する 環境設定 › モデル で設定します。Agents グループが表示されるのは、以前のリリースで保存したエージェントのキーをまだ持っているワークスペースだけで、その 「モデル」で編集… メニュー項目で 環境設定 › モデル が開きます。モデルへのアクセスを変更するには、環境設定 › モデル かマシンの モデル ペインを使います。

認証情報ごとの 承認 のゲート(使用前に確認)と、各サービスの 書き込みポリシー は、ここではなくガードレールペインで設定します。フィールドごとのリファレンスは設定 → 認証情報を参照してください。

7 つのプロバイダーは 自動で処理 されます――Anthropic、OpenAI、GitHub、GitLab、DigitalOcean、Twilio、Kubernetes には手動のトークンルールは不要で、それぞれ専用のセクションで扱います。それ以外はすべて その他の API キー を使います。

env ファイルからの取り込み。 env ファイルを読み込む… は既存の .env ファイル――または ~/.bashrc――を読み、その変数を認証情報に変換します。パーサーは KEY=VALUE と export KEY=VALUE を扱い、囲んでいる引用符と行末のコメントを取り除き、シェルでの評価が必要なもの($VAR の展開や $(…) の置換)は意図的にスキップするので、実際の .bashrc を指定しても安全です。続いて確認シートに、値を 伏せた 状態で変数が表示されます。認識される名前(GH_TOKEN/GITHUB_TOKEN、GITLAB_TOKEN、AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN、DIGITALOCEAN_ACCESS_TOKEN、LINEAR_API_KEY、TWILIO_ACCOUNT_SID/TWILIO_AUTH_TOKEN、そしてモデルプロバイダーのキー ANTHROPIC_API_KEY、OPENAI_API_KEY、XAI_API_KEY、MOONSHOT_API_KEY、KIMI_API_KEY。これらは 環境設定 › モデル の対応するプロバイダーへ――リモートマシンの場合はそのマシン独自の モデル の上書きへ――入ります)は自動的に対応する認証情報の種類に割り当てられ、認識されない名前は、カンマ区切りで指定したホスト範囲を持つ汎用の手動トークンとして取り込めます。すでに設定済みのエントリには印が付いてチェックが外れた状態になるので、取り込み直しで秘密情報が黙って上書きされることはありません。

エージェントのキーとサブスクリプション

すべてのコーディングエージェント――Claude Code、Codex、Grok、Kimi、omp――は、環境設定 › モデル(⌘, を押して モデル)で設定した プロバイダー からモデルへのアクセスを得ます。同じペインが各マシンの設定にも、マシンごとの任意の上書きとして存在します。プロバイダー、エージェントごとのモデル選択、マシンごとの上書き、OpenRouter、カスタムサーバー、オンデバイスモデルといった完全なリファレンスはモデルとプロバイダーにあります。このセクションでは、認証情報にとって重要なこと――キーやサブスクリプションが VM に一切入らずにどうエージェントへ届くか――を扱います。

「Bromure — 環境設定」というタイトルの環境設定ウインドウ、デフォルトのページ、モデルペイン:プロバイダーの列(API キーと緑のドットがある Anthropic (Claude)、OpenAI、OpenRouter と、未設定の xAI (Grok)、z.ai (GLM)、Moonshot (Kimi)、Amazon Bedrock、カスタムサーバー、オンデバイス)とエージェントの列(サイズ付きのデフォルト、Claude Code、Codex、Grok、Kimi、omp)

プロバイダー の列でプロバイダーをクリックすると、そのポップオーバーが開きます。どのプロバイダーにも API キー フィールドがあり、サブスクリプションを提供する 4 つのプロバイダーにはサインインの操作もあります。

API キー

ポップオーバーの API キー フィールドにキーを貼り付けます。環境設定では入力すると同時に保存され、マシンの設定では 保存 で保存されます。ライフサイクル:

  • VM 内: エージェントのいつもの変数(ANTHROPIC_API_KEY、OPENAI_API_KEY、XAI_API_KEY、…)には、プロバイダーの形式に合わせたダミー(sk-ant-api03-brm-…、sk-brm-…、xai-brm-…、sk-kimi-brm-…)が入ります。
  • 通信経路上: そのプロバイダーのホスト(anthropic.com、openai.com、x.ai、moonshot.ai、…)へのリクエストでのみ、本物のキーに差し替えられます。
  • 保存時: キーはモデル設定のほかの部分と同様に、models.enc に暗号化して保存されます(ホスト上の秘密情報の保存場所を参照)。

モデル で設定したキーは、資格情報ペインにもガードレールペインにも表示されないため、使用前に確認 の行はありません。(以前のリリースでワークスペース自体に保存されたままのエージェントのキーはそこに表示され、承認の対象にできます。env ファイルの取り込みでは、もうそのようなキーは作られず、エージェントのキーはモデル設定に入ります。)

CLI では、bromure-cli workspaces create --auth token|subscription|bedrock|local と bromure-cli vm run --auth token|subscription|bedrock|local で、引き続きワークスペースのプライマリエージェントの認証モードを選べます。

サブスクリプション:Claude、ChatGPT、Grok、Kimi

API キーではなくサブスクリプションを持っている場合は、代わりにサインインします。サブスクリプションがあるのは Anthropic (Claude)、OpenAI(ChatGPT。Codex が使用)、xAI (Grok)、Moonshot (Kimi) だけです。z.ai、Amazon Bedrock、OpenRouter、カスタムサーバーはキーのみ、omp は API キーのみです。サブスクリプションが動かすのは自分のエージェントだけです。Claude のサインインは Claude Code を、ChatGPT のサインインは Codex を動かす、という具合です。

どの方法でサインインしても結果は同じです。本物の OAuth トークンはホストにだけ存在し、ゲストは偽のキーで動きます――Claude には偽の ANTHROPIC_API_KEY、Codex には遠い将来に期限が切れる偽の JWT を入れた ~/.codex/auth.json(クライアントが更新しようとしないように)、Grok と Kimi にはそれぞれの認証情報ファイル内の代用トークンです。プロキシは偽の値を認識し、通信経路上で有効な Authorization: Bearer アクセストークンを注入します。

環境設定 › モデルからのサインイン

プロバイダーのポップオーバーは、次の 3 つの状態のいずれかを表示します。

状態ポップオーバーの表示
未サインインSign in with プロバイダー、「一時的な VM での対話型ログイン — API キーは不要です。」、そして API キー フィールドの上に「または API キーを貼り付け」。
サインイン済みサインインした日付付きの緑の「サインイン済み」の行、再度サインイン…、ログアウト…。
期限切れオレンジの サインインの期限切れ パネル――「プロバイダー が保存済みのサインイン(…)を拒否しました。再度サインインするまで、セッションはこれを使用できません。」――と 再度サインイン、ログアウト…。

Sign in with プロバイダー で登録フローが始まります。

  1. プロバイダー に登録 というタイトルの説明が、これから何が起きるかを示します。続行 をクリックします。(Bromure のプロキシが動いていない場合、登録は拒否されます。)
  2. 使い捨ての登録用 VM が起動します――一時的で分離されており、ワークスペースのフォルダも、保存された秘密情報も、認証情報の差し替えマップもありません。その中で、エージェント自身のログインコマンドが実行されます。
  3. Mac の既定のブラウザでプロバイダーのサインインページが開きます。いつもどおりサインインします。
  4. 得られたトークンはホストで取り込まれ、暗号化して保存されます。使い捨ての VM はシャットダウンされ、削除されます。

環境設定から始めたサインインは、常にすべてのマシンで共有されます。ログアウト… は「プロバイダー からログアウトしますか?」――「このサインインを使用しているワークスペースは、再度サインインするまで動作しなくなります。」――と尋ね、保存されたサインインを削除します。ログアウト… は、操作できない場所では表示されません。

マシンのモデルペインからのサインイン:共有範囲

同じポップオーバーは、マシン独自の モデル ペインにも表示されます。そこで始めたサインインは、最後に すべてのワークスペースで共有しますか? という質問で終わります。

ボタン効果
すべてのワークスペースサインインを共有のものとして保存し、さらに そのプロバイダーについて各マシン独自のサインインを削除するので、どのマシンも実際に新しいサインインを使うようになります。
このワークスペースのみこのマシンのためだけにサインインを保存します。

範囲が重要なのは、マシンがまず自分のサインインを読み、それがないときだけ共有のサインインを使うからです。一度自分用にサインインしたマシンは、より新しい共有サインインができても、すべてのワークスペース を選ぶかそのマシンをログアウトさせるまで、そのサインインを使い続けます。サインインを開始したリモートクライアントにも同じ質問が表示され、誰も答えなければ、サインインはそのマシンだけのものになります。

チャットからのサインイン

先に環境設定を開く必要はありません。セッション内のエージェントがサインインを必要とすると、チャットに プロバイダー にサインイン というタイトルのカード――「Bromure はこの Mac でサインインし、プロバイダー のアカウントをマシンから遠ざけます — エージェントには代替キーしか見えません。」――が プロバイダー にサインイン… ボタン付きで表示され、サイドバーのセッションの行には サインインが必要 と表示されます。エージェントの保存済みサインインが拒否された場合も、赤いエラーカードに同じボタンが表示されます。

クリックすると、使い捨ての VM を使わずにサインインします。

  1. セッション自身のターミナルでエージェントのログインコマンドが実行され、Mac のブラウザでプロバイダーのサインインページが開きます(「サインインのためにブラウザを開いています…」)。
  2. エージェントが認可コードをトークンと交換するとき、プロキシ自身がその交換に応答します。本物のトークンはそのままホストの保存領域に入ります。Claude Code と Codex には認証情報が Mac に残ることが伝えられ、Grok と Kimi は代用トークンを受け取り、それぞれの CLI がそれを認証情報ファイルに書き込みます。
  3. エージェントは代用値で再起動します(「サインインしました。… を再起動しています…」)。

チャットからのサインインは、そのマシンが読んでいたサインインを置き換えます。マシン独自のものがあればそれを、なければ共有のものを置き換えます。5 分以内にプロキシにサインインが届かなければ、カードに「Bromure は プロバイダー のサインインを時間内に受け取れませんでした。もう一度お試しください。」と表示されます。1 台のマシンで同時に実行できるサインインは 1 つだけです。

omp にはサインインするアカウントがないため、そのカードには「omp にはモデルプロバイダが必要です」と表示され、代わりに マシンの設定… が表示されます。

警告: 期限切れのサインインを直すために、VM 内で /login(またはエージェントのログインコマンド)を手動で実行しないでください。トークンが VM に残らずホストに取り込まれるよう、カードか 環境設定 › モデル を使ってください。

Kimi は国際リージョンにサインインする

Kimi Code の CLI は既定で中国本土のリージョンを使い、そこではほかの地域のアカウントが拒否されます。Bromure は、登録用 VM とすべてのセッションで CLI のリージョン変数を設定し、Kimi を国際リージョン(auth.kimi.ai、API は api.kimi.ai)にサインインさせます。以前の auth.kimi.com リージョンで取り込んだ Kimi のサインインも引き続き認識されます。

トークンの管理:1 つの許可に 1 つの更新役

トークンの更新はすべてホスト側で行われ、各サインインはただ 1 つの所有者によって更新されます。

  • スロットごとに 1 つの許可。 共有のサインインと各マシン独自のサインインは、別々のスロットです。スロットごとに同時に動く更新は 1 つだけで、そのスロットを読むすべてのマシンがその結果を使います。ゲストがリフレッシュトークンを持つことはありません。
  • 更新のタイミング。 ホストは期限切れの約 5 分前に、プロバイダーのトークンエンドポイント(Claude は platform.claude.com、Codex は auth.openai.com、Grok は auth.x.ai、Kimi は auth.kimi.ai)に対して更新します。登録したばかりのサインインは期限切れの状態で保存されるので、最初の使用で更新経路が機能することが確かめられます。
  • 自動化用のクローンは許可を共有する。 自動化のためにクローンされたマシンは、ベースマシンのサインインをコピーせずに参照します。
  • Mac 自身の CLI のログインは取り込まれない。 ホスト上の CLI と許可を共有すると、片方が更新するたびにもう片方がログアウトされてしまいます。
  • 使えるトークンがない場合、 Claude へのリクエストについて、プロキシは偽のキーを転送する代わりに自らエージェントに応答します。一時的な障害は再試行可能な 529 として、拒否されたサインインは Bromure から再度サインインするよう促す 401 として返ります。ポップオーバーには サインインの期限切れ が表示されます。

サービスの認証情報

AWS

AWS はどのプロバイダーよりも深く扱われます。なぜなら AWS リクエストはベアラートークンで認証されるのではなく、署名されるからです(SigV4)。ワークスペースエディタで認証情報 → AWSを開きます。セグメントコントロールで Static keys と SSO / Identity Center のいずれかを選びます。

静的キーとホストの再署名器

Access key ID と Secret access key(さらにオプションの STS Session token と Default region)を貼り付けます。ライフサイクルは次のとおりです。

  • VM 内: ~/.aws/config は credential_process ヘルパーを指し、これは vsock ポート 8445 経由で、本物の Access key ID と 40 文字の偽の Secret access key の組を提供し、セッショントークンは省略します。あらゆる AWS SDK、aws CLI、terraform、boto3 がこれをネイティブに取り込みます。ツール固有のセットアップは不要です。
  • ゲストが行うこと: 偽のシークレットでリクエストに署名し、構文的には有効だが暗号学的には破綻した SigV4 署名を生成します。
  • 通信経路上: ホストの AWS 再署名器は、あらゆるパーティションの AWS 宛てのリクエストを、IPv4 名でもデュアルスタック名でも検出し(*.amazonaws.com、*.api.aws、*.amazonaws.com.cn、*.api.amazonwebservices.com.cn、European Sovereign Cloud と ISO パーティションのドメイン。GovCloud、リージョン別、FIPS、バケット形式の S3 ホストを含む)、ゲストの署名を取り除き、セッショントークンがあれば本物の X-Amz-Security-Token を注入し、リクエストが Mac を出る前に本物のシークレットで再署名します。AWS ガードレールも同じホストを対象とし、後述の VM が作成する認証情報の書き換えはこれらに加えて public.ecr.aws も対象とします。再署名に成功するたびに、アクセスキーを伏せた credential.aws_sign 監査イベントが出力され、セキュリティ タイムラインに 資格情報の使用 の行として表示されます。

これは最も強い意味でフェイルクローズです。本物のシークレットキーはいかなる形でも VM 内に存在せず、プロキシを迂回したリクエストは AWS によって InvalidSignatureException で拒否されます。

次の 3 つのリクエスト形式はサポートされておらず、暗黙の失敗ではなくゲストに明確なエラーを返します。チャンク化されたストリーミング S3 アップロード(STREAMING-AWS4-HMAC-SHA256-PAYLOAD、501 で応答)、SigV4A 非対称署名、および事前署名されたクエリ文字列 URL(署名を再署名器が置き換えられない位置に埋め込むもの)です。

VM が作成する認証情報

一部の呼び出しは新しい認証情報を発行します。aws sts assume-role / get-session-token / get-federation-token、aws iam create-access-key、IAM Identity Center のロール認証情報、Cognito の GetCredentialsForIdentity、aws ecr get-login-password、そして DigitalOcean では doctl registry login、doctl kubernetes cluster kubeconfig save(およびその認証情報の呼び出し)、doctl spaces keys create です。プロキシはこうした呼び出しへのレスポンスを保留し、VM に渡す前にその中のすべてのシークレットを偽物に置き換えます。一時的な AWS キーは本物の Access key ID を保ったまま、シークレットとセッショントークンだけが偽物になるため、再署名器はゲストがどのキーで署名したかを判別できます。レジストリやクラスターのトークンは偽物になり、そのレジストリまたはクラスターに対してだけ本物に戻されます。

本物の値はワークスペースの構成に暗号化して保存されるため、VM が保存した偽物(~/.aws、~/.docker/config.json、または kubeconfig 内)は再起動後も機能し続けます。発行された AWS キーは、そのキー自身のシークレットとセッショントークンで再署名されます。有効期限が切れると、そのキーで署名されたリクエストはワークスペース自身のキーで再署名されるのではなく拒否されます。再署名すれば別の ID として実行されてしまうからです。期限切れの認証情報は、期限切れから 30 日後に破棄されます。

プロキシが完全に書き換えられないレスポンスは決して渡されず、ゲストには代わりに 502 が返ります。VM 自身が選んだシークレットを設定する呼び出しは、どんな偽物でも代替できないため、どのガードレールモードでも拒否されます。対象は iam:CreateLoginProfile、UpdateLoginProfile、CreateServiceSpecificCredential、ResetServiceSpecificCredential です。AWS の同意プロンプトは署名しようとしている呼び出し(たとえば sts:AssumeRole)を示し、発行された認証情報ごとに credential.minted イベントが出力されます。

SSO / IAM Identity Center

組織が IAM Identity Center を使用している場合、長期キーを貼り付ける代わりに SSO / Identity Center を選びます。

  1. Grant access to ~/.aws をクリックし、フォルダアクセスのプロンプトを承認します(セキュリティスコープ付きの許可です。フォルダはホスト上で読まれ、VM にマウントされることはありません)。
  2. SSO profile ピッカーからプロファイルを選びます。アプリは ~/.aws/config 内で sso_start_url、sso_account_id、sso_role_name を持つ [profile …] セクションを見つけ、[sso-session …] 参照を解決します。アカウント ID とロールは読み取り専用で表示されます。
  3. セッション開始時、ホストは SSO トークンキャッシュ(~/.aws/sso/cache)から一時的なロール認証情報を解決します。キャッシュされたトークンが期限切れの場合、aws sso login のためにブラウザが開きます — これはホスト上で、/usr/local/bin/aws から実行されます。

解決された一時キーは、静的キーと同じ再署名器に供給されます。VM は依然としてシークレットを目にすることはありません。認証情報は、有効期限の約 5 分前にホスト上で自動リフレッシュされます。

Bedrock

Amazon Bedrock は、1 つのエージェントの認証モードではなく、すべての エージェントのためのモデルプロバイダーです。環境設定 › モデル(またはマシンの モデル ペイン)の Amazon Bedrock ポップオーバーで Amazon Bedrock を使用 をオンにし、エージェントごとに Bedrock のモデル ID を選びます。Claude Code は Bedrock でネイティブに動き、ほかのエージェントは Bedrock の OpenAI 互換 API を通じて利用します。Bedrock のエンドポイントは *.amazonaws.com のホストなので、リクエストは同じ再署名経路で各マシン自身の AWS 認証情報(資格情報 → AWS、静的または SSO)によって署名されます――または、ポップオーバーの Bedrock API キー(省略可 — 省略時は AWS 資格情報で署名) フィールドにキーを貼り付けた場合はそのキーで署名され、VM にはそれが bedrock-brm-… のダミーとしてしか見えません。ポップオーバーでは AWS リージョン も指定できます。空欄にすると、各マシンの AWS リージョンが使われます。モデルとプロバイダーを参照してください。

Git HTTPS トークン(GitHub、GitLab、Bitbucket、セルフホスト)

git-over-HTTPS 用のパーソナルアクセストークンは、GitHub Tokens / GitLab Tokens / Bitbucket Tokens(総称して HTTPS トークン)の下にあります。各エントリはホスト、ユーザー名、トークンを受け取ります。セルフホストの GitLab や Gitea のインスタンスは、ホストフィールドを設定することで機能します。ライフサイクルは次のとおりです。

  • VM 内: 偽物が ~/.git-credentials および gh/glab の設定に書き込まれます。GH_TOKEN と GITLAB_TOKEN がエクスポートされ、CLI が自動的に認証します。偽物の形状は各ベンダーのバリデーターに一致するため(GitHub は ghp_ + 36、GitLab は glpat- + 20、それ以外は brm_…)、gh と glab のプレフィックスと長さのチェックを通過します。
  • ワイヤ上: そのエントリの git ホストへのリクエストで本物のトークンに差し替えられます。
  • 承認: 各エントリはガードレールペインに独自の使用前に確認の行を持ちます。

SSH 経由の git push だけが必要なら、HTTPS トークンはまったく不要かもしれません — 以下の SSH キーを参照してください。

汎用 API キー(その他の API キー / 手動トークンルール)

アプリが自動処理しない任意の API については、その他の API キー(手動トークンルール、MITM token swap としても表示されます)の下にエントリを追加します。Add token をクリックし、次を指定します。

フィールド意味
Nameエントリのラベル。
Value本物のシークレット(ホスト上に暗号化されて保管されます)。
Env var nameVM 内で偽物がエクスポートされる変数。コードからこれを参照します。
Host filter (optional)差し替えのホストスコープ。

2 つのエッジケースが意図的に用意されています。

  • 空の env var name: 何もエクスポートされません。セッションのウェルカムバナーから偽物をコピーし、ツールが必要とする場所に配置します。
  • 空白のホストフィルター: 本物の値が、尋ねることなく任意のホストで注入されます。これは明示的な常時オンの選択であり — 多くのリージョン別ホスト名を持つ API に便利です — が、認証情報のスコープがもはやそれを保護しないことを意味します。スコープのないシークレットをゲートするには、ガードレールペインでそれの使用前に確認をオンにします(あるいは結局のところホストフィルターを与えます)。

Anthropic、OpenAI、GitHub、GitLab、DigitalOcean、Kubernetes は、ここで手動エントリを必要とすることは決してありません。

1Password シークレット参照(op://)

本物のシークレットを貼り付ける代わりに、その他の API キーの値は 1Password シークレット参照 — op://vault/item/field、または op inject や .env.op ファイルが使用する波括弧形式 {{ op://vault/item/field }} — にできます。ディスク上に保管されるのは参照だけであり、シークレット自体はホストや VM のどこにも書き込まれません。エディタはこの参照を認識し、平文で表示し(それはシークレットではありません)、1Password を通じて解決されることを注記します。

各ワークスペースの起動時に、Bromure は 1Password CLI(op read)でホスト側で参照を解決し、参照文字列から偽物を発行し(そのためシークレットがローテーションしても偽物は安定して保たれます)、その偽物だけを VM にエクスポートします。その後 MITM プロキシは、貼り付けられたシークレットに対してそうするのとまったく同じように、ワイヤ上で偽物を解決された値に差し替えます — そして2 分ごとに再解決するため、1Password でアイテムをローテーションしても、再起動なしに数分以内に反映されます。

これには op CLI がインストールされ、サインインしている必要があります — 1Password アプリによる生体認証のロック解除、またはターミナルでの op signin です。op が見つからない場合、エディタは Get 1Password CLI リンクを表示し、ワークスペースは起動時にインストール手順を提示します。解決が失敗した場合(サインインしていない、またはアイテムが存在しない場合)、Bromure はエラーを提示するので、それを修正してワークスペースを再起動できます。

.env や .env.op ファイルを取り込むと(資格情報ペインの env ファイルを読み込む…)、ANTHROPIC_API_KEY のような認識される名前でも、STRIPE_KEY のような任意の名前でも、op:// の値が自動的に認識され、それぞれ参照を保持する手動トークンとして保存されます。

DigitalOcean

認証情報 → DigitalOcean の下にパーソナルアクセストークンを貼り付けます(Open DigitalOcean token page in your browser リンクはトークン生成へ移動します)。偽物(dop_v1_ + 16 進、64 文字)は DIGITALOCEAN_ACCESS_TOKEN としてエクスポートされ、~/.config/doctl/config.yaml に書き込まれるため、doctl auth init は不要です。差し替えは digitalocean.com へのリクエストを対象とし、加えて registry.digitalocean.com に対する docker login / doctl registry login で使用される base64 の Basic 認証ブロブ用の 2 つ目のエントリもあるため、レジストリのプッシュとプルも解決されます。

Linear

個人 API キーを 資格情報 → Linear に貼り付けます(リンク:ブラウザで Linear の API 設定を開く。キーは linear.app → Settings → API で取得できます)。ダミー(lin_api_ + 40 文字)は LINEAR_API_KEY としてエクスポートされ、Linear の SDK、MCP サーバー、CLI ツールが自動的に読み取ります。差し替えは linear.app(GraphQL は api.linear.app、MCP は mcp.linear.app)に厳密に限定されます。ワークスペースに Linear のキーがあることは、Linear の課題をトリガーとする自動化の前提条件でもあります――自動化を参照してください。

Twilio

Twilio API key の認証情報を追加し、Account SID (AC…) or API Key SID (SK…) に SID を、Auth Token / API Key secret にシークレットを入力します(どちらも console.twilio.com で取得)。Twilio は HTTP Basic 認証を使い、SID は ID――リクエストの URL に含まれて送られます――で、秘密なのはトークンだけです。ライフサイクル:

  • VM 内: TWILIO_ACCOUNT_SID には本物の SID が、TWILIO_AUTH_TOKEN には brm-twilio-… のダミーが入るので、Twilio の SDK と CLI は設定なしでそれを読み取ります。
  • 通信経路上: twilio.com へのリクエストで、プロキシはダミーのトークンそのものと、あらかじめ base64 エンコードされた Basic 認証の SID:トークン の両方を本物に差し替えます。
  • 承認: ガードレールペインの 使用前に確認 で設定します。

env ファイルを読み込む… は TWILIO_ACCOUNT_SID/TWILIO_API_KEY_SID と TWILIO_AUTH_TOKEN/TWILIO_API_SECRET を認識し、1 つの Twilio 認証情報にまとめます。

MCP サーバーのベアラートークン

MCP ペインで構成された HTTP トランスポートの MCP サーバーは、同じ扱いを受けます。本物のベアラートークンはホスト上に留まり、brm-mcp_… の偽物がエージェントの読む MCP 設定に注入され、プロキシがサーバーのホストにスコープしてワイヤ上で差し替えます。差し替えエントリを受け取るのは、空でないベアラートークンを持つ、有効な HTTP トランスポートのサーバーだけです。

ひとつ追加の配慮があります。brm-mcp_ エントリを持つホストについては、プロキシは OAuth/OIDC のディスカバリーパス(.well-known の authorization-server、protected-resource、OpenID configuration の各エンドポイント)に 404 で応答します。すると Claude Code は、そのサーバーを事前認証済みとして扱い、自身の OAuth フローを試みなくなります — いずれにせよ VM 内では決して完了できないフローです。

コンテナレジストリ(Docker Hub、GHCR など)

認証情報 → Container Registries は、docker pull/push 用の HTTP Basic 認証を管理します。Docker Hub(docker.io)、GitHub Container Registry(ghcr.io)、GitLab Container Registry(registry.gitlab.com)のプリセットがあります。その他のレジストリはホストで追加できます。ライフサイクルは次のとおりです。

  • VM 内: ~/.docker/config.json に偽の auth ブロブ — ユーザー名と導出された brm-docker-… パスワードを組み合わせた base64 — が含まれるため、Docker はログイン済みだと信じます。
  • ワイヤ上: プロキシは一致するレジストリホストで本物の base64 ブロブに差し替えます。distribution-spec のトークンのやり取りも処理されます。既知の認証レルム用に差し替えエントリが追加されます(Docker Hub は auth.docker.io に対して、DigitalOcean のレジストリは api.digitalocean.com に対して認証します)。
  • インポート: Import config.json… をクリックして、ホスト上の既存の ~/.docker/config.json からエントリを取り込みます。credsStore/credHelpers に委譲されたエントリはスキップされます — それらのパスワードはファイルではなく OS のキーチェーンにあります — そしてインポートの要約は、いくつがなぜスキップされたかを報告します。
  • 承認: レジストリごとに、ガードレールペインの使用前に確認を通じて行います。Remove this registry はエントリを削除します。

Kubernetes コンテキスト

認証情報 → Kubernetes は、kubeconfig のコンテキストをプロキシ経由のクラスターアクセスに変えます。Import kubeconfig をクリックして既存の kubeconfig を解析し、コンテキストごとに 1 行にする(current-context が最初、認証タイプは自動検出)か、Add context でサーバー URL、認証情報、名前空間、クラスター CA を手動で入力します。いずれの場合も、VM は合成された ~/.kube/config を受け取ります。ゲスト内の kubectl は(Bromure CA を通じて信頼される)プロキシと通信し、API サーバーと直接通信することは決してありません。

認証タイプごとに次のとおりです。

  • ベアラートークンコンテキストは VM 内で brm-k8s-… のプレースホルダーを受け取り、ワイヤ上で本物のトークンに差し替えられます。
  • クライアント証明書コンテキストは VM 内で使い捨ての自己署名証明書とキーを受け取ります。本物の証明書とキーはホスト上に SecIdentity として登録され、上流の mTLS に使用されます。
  • Exec プラグインコンテキストは、VM 内でプラグインをまったく実行しません。exec プラグインポーラーが、リフレッシュ間隔(デフォルト 600 秒、下限 60)ごとにホスト上でコマンドを実行し、ExecCredential JSON を解析し、新鮮なトークンを差し替えマップに供給します。リフレッシュはエントリの同意状態を保持します。

kubeconfig がクラスター自身の CA を供給する場合、それが転送され、プロキシが上流の API サーバーを検証できます。インポートされた kubeconfig 内のファイルパスのフィールド(CA、証明書、キー)は、インポート時に先読みで読まれます — ディスク上のそれらのファイルへの後の変更は取り込まれません。各コンテキストはガードレールペインに独自の使用前に確認の行を持ち、そこでは書き込みポリシーが、バイトが転送される前に破壊的な動詞(kubectl delete、AWS の Delete*/Terminate*、docker push、git push)をホスト側で追加的に取り除くこともできます — 認証情報の差し替えとは別の層です。

HTTP データベース(MongoDB、ClickHouse、Elasticsearch)

認証情報 → Databases(MongoDB / ClickHouse / Elasticsearch のセクション)は、HTTPS を話すデータベースエンドポイント — Mongo Data API、ClickHouse の HTTP インターフェース、Elastic — を扱います。各エンドポイントは、エンジン、ホスト、シークレット、ユーザー名、認証タイプ、および brm-db-… の偽物がエクスポートされる 1 つ以上の env var 名(カンマ区切り)を受け取ります。コードや接続文字列からそれらの変数を参照します。

データベース認証情報は、差し替えがヘッダーとクエリパラメータだけでなくリクエストボディも走査する唯一のファミリーです。なぜなら接続シークレットは、JSON や SQL のペイロードの中に日常的に乗って移動するからです。プロキシはボディの差し替え後に Content-Length にパッチを当てます。他のトラフィックの無関係な multipart やバイナリのボディが触られることは決してありません(他のすべての差し替えはヘッダーにスコープされています)。Basic 認証エンドポイントは、その base64 のユーザーとシークレットのブロブも差し替えられます。エンドポイントごとの使用前に確認と書き込みポリシーは、ガードレールペインで設定します。

SSH キー

SSH はトークンをまったく使わずに処理されます。VM の SSH_AUTH_SOCK は、vsock(ポート 8444)経由の ssh-agent ブリッジによって支えられています。ゲストはアイデンティティを一覧表示し署名を要求できますが、秘密鍵のバイト列はホスト上にのみ存在し、VM 内から物理的に読み取ることも抽出することもできません。キーのソースは 2 つあり、どちらも認証情報 → SSH Keys の下にあります。

  • ワークスペースごとのデフォルトキー。 共有のデフォルト ed25519 キーペアがアプリ起動時に生成され(Application Support の default-ssh/ の下に保管)、新しい各ワークスペースのエージェントディレクトリにコピーされます。ペインはワークスペースの公開鍵を表示するので、それを git ホストに貼り付けられます(GitHub の場合: github.com/settings/keys)。また bromure-cli workspaces ssh-keygen <workspace-id|name> で CLI から新鮮なキーを発行することもでき、これは新しい公開鍵を出力します。
  • インポートされたキー。 Imported SSH keys の下の Import… / Import file… をクリックし、既存の秘密鍵ファイルをアプリに指定します — RSA、ed25519、ECDSA がサポートされ、暗号化されたキーも含まれます。暗号化されたキーは、インポート時に一度だけパスフレーズを求めます。パスフレーズは macOS のキーチェーン(サービス io.bromure.agentic-coding.ssh-key-passphrases)に保管され、起動時に SSH_ASKPASS を介して供給され、決してログに記録されません。インポートされたキーの署名は、アプリが自身のために起動するプライベートな ssh-agent プロセス(一時ディレクトリ下のソケット上の ssh-agent -D)を通ります — システム上の他の何とも分離されています。
  • ホストのエージェントの鍵。 秘密鍵がデバイスの外に出られない鍵 — gpg-agent、Secretive、1Password の背後にある YubiKey などのセキュリティキー — は、代わりに From host agent… で追加します。エージェントのソケットを選び(空欄 = アプリ自身の SSH_AUTH_SOCK。Finder から開いたアプリでは、シェルがエクスポートしているものではなく macOS のエージェントです。gpg-agent なら ~/.gnupg/S.gpg-agent.ssh を使います)、Load をクリックして、ワークスペースが使ってよい鍵にチェックを入れます。何もコピーされません。VM に見えるのはチェックした鍵だけで — しかもエージェントがそれを保持している間だけなので、抜いた鍵は提示されません — その署名リクエストはそのエージェントに転送されるため、タッチや PIN の確認はいつもどおり Mac に表示されます(リクエストは最大 2 分間それを待ちます)。エージェントのほかの鍵は VM からは見えず、それらで署名するリクエストは拒否されます。

インポートされたキーごとに、ガードレールペインで使用前に確認をオンにすると、VM 内のすべての署名リクエストが同意を求めるようになります。すべての署名 — デフォルトキーであれインポートされたキーであれ — は、キーの SHA256 フィンガープリントと、それが管理されたキー、インポートされたキー、ホストのエージェントの鍵のいずれかを運ぶ credential.ssh_sign 監査イベントを発行します。

メモ: あなたの macOS ログインの ssh-agent(launchd のもの)— あるいはほかのどのホストのエージェントも — は、意図的に 決して 丸ごと VM に公開されません。セッションから到達できるのは、ワークスペースごとのキー、あなたが明示的にインポートしたキー、そして個別に選んだホストのエージェントの鍵だけです。

利用ごとの承認と付与期間

本章のあらゆる認証情報は使用前に確認のフラグを立てられます — ガードレールペインの認証情報ごとのチェックボックス(コントロール自体には Require approval to use と表示)で、デフォルトではオフであり、UI では「このセッションでこの認証情報が最初に使用されるときに確認ダイアログを表示します。」と説明されます。

ゲートされた認証情報がセッションで最初に使用されると、プロキシはリクエストを保留し、Allow "workspace name" to use credential? と題した同意ダイアログを表示します(ワークスペースの名前と認証情報のラベルが埋め込まれます)。4 つのボタンが提供されます。

ボタン付与
Allow for 5 minutes時間制限付き。認証情報は 5 分間、それ以上のプロンプトなしで流れます。
Allow for 1 hour時間制限付き、1 時間。
セッション中ずっと許可マシンの VM がシャットダウンするまで。
Don't allowリクエストは拒否されます。拒否は 5 分間記憶されるため、エージェントのリトライの嵐がダイアログの嵐を生み出しません。

知っておくと役立つ挙動は次のとおりです。

  • 合体。 同じ認証情報を必要とする並行リクエストは、1 つのダイアログに集約されます — おしゃべりなエージェントが 12 個の並列 API 呼び出しを放っても 1 つのプロンプトになり、12 個すべてがあなたの決定に従います。
  • 拒否が勝つ。 生きている拒否は、それより古い許可が参照される前に短絡します。
  • 設計上、一時的。 許可と拒否はメモリ上にだけ保持され、VM がシャットダウンすると取り消されます。「セッションの残り」が VM の再起動をまたぐことはなく、アプリの実行をまたいで保存されるものもありません。
  • ヘッドレスセッション。 SSH やヘッドレスのセッションでは、確認は GUI のアラートではなくマシンの tmux 内に表示されます――リモートアクセスを参照してください。

AWS については、ゲートはすべてのホスト側の署名呼び出しに適用されます。SSH キーについては署名リクエストに、それ以外のすべてについてはセッションでの最初のワイヤ差し替えに適用されます。

ヒント: 同意ゲートは認証情報ごとであり、ホストごとではありません。スコープのない手動トークンを制御下に留めたいなら、承認がそのために設計された仕組みです。

認証情報の承認ウィンドウ

Window → Credential Approvals… は、現在のアプリの実行中に行われたすべての同意決定 — 時間制限付きの許可(5 分 / 1 時間 / セッションの残り)と記憶された拒否 — のライブビューを開きます。各行はワークスペース名と残り時間を表示し、Revoke を提供します。Revoke all(⌘⌫)はすべてを一度にクリアします。リストは 2 秒ごとに自動更新され、付与が期限切れになるにつれて自然に縮みます。

判断はメモリ上にしかないため、許可の期限が切れたあと、VM がシャットダウンしたあと(セッション単位の許可)、アプリを終了したあとは、ウインドウは空になります。これは現在のためのコントロールパネルであり、監査ログではありません――履歴にはセキュリティ タイムラインとトレースを使ってください。

侵害検出器

偽物は二重の役割を果たします。シークレットの代役を務めるだけでなく、**トリップワイヤー(仕掛け線)**でもあります。偽トークンには、正当な宛先ファミリーがちょうど 1 つ — それが発行されたホストスコープ — だけあります。sk-ant-api03-brm-… が pastebin.example へのリクエストに現れる正直な理由はありません。そこでプロキシは、すべての送出リクエスト — ヘッダーとボディ — を、Aho-Corasick オートマトン(すべてに対して実行できるほど安価)で走査し、スコープの外へ向かうあらゆる偽物を探します。

それが見つかると、プロキシはそのリクエストを認証情報の持ち出しの試みとして扱います。

  1. リクエストは HTTP 451 でブロックされます。1 バイトも宛先に転送されません。
  2. VM はただちに 一時停止 します。マシンがバックグラウンドで動いていた場合は、まず画面に表示され、その静止画面が赤く染まります。
  3. この環境は侵害されている可能性があります というタイトルの重大なアラートが表示されます:「Bromure は「マシン」からセッション認証情報を、発行先ではないホストへ漏らそうとする外向きの試みを検出しました。VM は一時停止されています。」検出された漏えい: の下に、漏えいごとに 1 行――トークンのプレビュー(sk-a…f9q3 など)、認証情報の名前、発行先のホスト、送信先のホスト――が並びます。
  4. 検出はセキュリティ タイムラインに赤い 資格情報ブローカー の行として記録され、登録済みのインストールでは credential.exfiltration イベントとしても記録されます。

アラートには 4 つのボタンがあります。

ボタン効果
シャットダウン(既定)VM を停止し、マシンを侵害済みとしてマークします。
ブロックこのリクエストだけを止め(すでに 451 が返っています)、VM を再開します。何も記憶されないため、エージェントが再び試みると検出器がまた反応し、アラートが再び開きます。
許可観測されたホストを このセッションの残りの間だけ 信頼し、VM を再開します。以後、認証情報は差し替えられてそのホスト(とそのサブドメイン)に送られ、そこへのリクエストには印が付かなくなります。判断は緑の 資格情報ブローカー の行「allowed by user for this session」として記録され、登録済みのインストールでは credential.exfiltration_allowed としても記録されます。許可リストは VM のシャットダウン時に消去されます。
調査用に保存フォルダを尋ね、disk.img(VM のシステムディスクのコピー)、home.tar.gz(マシンのホームディレクトリ)、共有フォルダごとの shares/<名前>.tar.gz を書き出したあと、VM をシャットダウンしてマシンを侵害済みとしてマークします。VM の RAM の状態は破棄されます。

Return キーに反応するのは シャットダウン だけです。ブロック、許可、調査用に保存 にはキーボードの操作がないため、敵対的かもしれない VM を再開する――ましてや認証情報を送る――には、必ず明示的なクリックが必要です。アラートは一度に 1 つだけ表示され、開いている間に繰り返された検出は破棄されます(それぞれは引き続きブロックされます)。

ヒント: 許可 は、正当な複数ホストにまたがる構成のためにあります――たとえば、ツールが OpenAI 形式のキーを意図的に別のプロバイダーの OpenAI 互換エンドポイントへ送る場合です。宛先に心当たりがなければ、許可しないでください。

マシンがリモートクライアントからミラーされている場合、質問はクライアント側に シャットダウン、ブロック、許可 を備えた保留中の確認として表示されます(調査用の保存にはローカルのフォルダピッカーが必要なため、Mac 自体でのみ提供されます)。一時停止するのは影響を受けた VM だけで、ホストはほかのすべてのマシンへのサービスを続けます。応答のない確認は、3 分後に VM をシャットダウンします。

侵害済みとしてマークされたマシンは、対処するまで起動を拒否します。起動しようとすると 「To continue, the VM disk image and the persistent home folder must be wiped. Your tokens, ssh keys, and workspace settings are preserved.」 と表示され、消去して起動 と キャンセル が示されます(Return キーでは消去は確定しません)。添えられた警告に注意してください:共有フォルダは消去されません。侵害が共有フォルダ内のパッケージやファイルから来た場合、それはまだ残っているかもしれません――作業を再開する前に、それらのフォルダを確認してください。

侵害アラートへの推奨される対応は、トレースインスペクタ(⇧⌘I)を開くか bromure-cli trace leaks を実行して問題のホストとリクエストを確認し、プロジェクトの依存関係とプロンプトインジェクションされた指示のどちらが原因かを判断し(プロンプトインジェクションとサプライチェーンを参照)、その後に消去して再起動することです。

スコープの詳細は次のとおりです。

  • スコープのない偽物は対象外。 ホストフィルターが空白の手動トークンは、設計上「任意のホスト」であり、検出器を作動させることはできません。ダミーのサブスクリプションプレースホルダーも同様に除外されます。
  • ファーストパーティの兄弟は許容される。 マッチングは差し替えのスコープポリシーをミラーしますが、1 つだけ緩和があります。認証情報のプロバイダーと同じ登録済みドメイン配下のホスト(たとえば anthropic.com 配下の Claude または Codex のインフラ)はファミリーマッチを使用するため、正当な api.anthropic.com トークンが mcp-tools.anthropic.com で見られても誤検知にはなりません。それ以外はすべて厳密です。
  • 本物らしい漏洩もフラグされる。 偽物のトリップワイヤーとは独立に、プロキシは送出トラフィック内の差し替えられていない、本物らしいシークレット — 既知のプレフィックス(sk-ant-、ghp_、AKIA など)を持つ Bearer や x-api-key の値、または 20 文字以上の不透明なトークン — をフラグします。これらはトレースインスペクタと bromure-cli trace leaks に漏洩警告として現れます。通常これは、本物のシークレットが手作業で VM に貼り付けられたことを意味し、ワイヤ境界はそれを不要にするために存在します。

検出器そのものは常に有効です。マシンごとにオフにできるのは中断のほうです――次のセクションを参照してください。

回避策

ホストやクライアントによっては、完全な傍受の下では動きません。ホストが信頼しないプライベート CA のサーバー、サーバーの証明書をピン留めするクライアント、あるいは侵害アラートを何度も引き起こしてしまう正当な構成などです。ガードレールペインの下部にあるマシンごとの 3 つの設定は、そうした場合に境界をオフにせずに緩めます。3 つとも再起動なしで即座に反映されます。

設定既定値動作
リクエストごとの安全でないバイパスを許可(X-bromure-insecure)オン自己署名またはプライベート CA のホストへのリクエストが証明書の検証に失敗した場合、エージェントは X-bromure-insecure: yes ヘッダーを付けて再試行し、その 上流の証明書の検証を省略できます。傍受、トレース、漏えい防止は有効なままで、そうしたリクエストには Bromure は本物の認証情報を 一切 注入しません――外に出るのはゲストのダミーだけです。使用のたびに、セキュリティ タイムラインに 上流 TLS の行「allowed — certificate validation skipped (X-bromure-insecure); no credentials injected」として記録されます。ゲストがヘッダーを送ったときにだけ作用するので既定でオンです。ヘッダー自体を禁止するにはオフにします。
透過インターセプトを無効にするオフVM の HTTP/HTTPS を強制的に Bromure に通す、ネットワークレベルの振り向けを止めます。生ソケットや証明書をピン留めするクライアントは、本物のネットワークと本物の上流証明書に直接到達するようになります。プロキシ自体は残ります。HTTP(S)_PROXY は設定されたままなので、プロキシに対応するツール(apt、git、pip、curl、node…)とエージェント自身の API 呼び出しは引き続き Bromure を通り、認証情報の差し替え、トレース、ガードレールが維持されます。プロキシ設定を無視するトラフィックは、送信ルールの対象外になります。
認証情報の流出時に警告しないオフ侵害アラートと VM の一時停止を抑止します。漏えいしようとするリクエストは それでも 451 でブロックされ、それでも セキュリティ タイムラインに記録されます(「blocked — exfiltration attempt (alerts off, VM not paused)」)。なくなるのは中断だけです。

警告: いずれの設定も、互換性と引き換えに保護を少し手放すものです。できるだけ範囲の狭いものを選んでください。信頼できない証明書 1 つにはリクエストごとのヘッダーを、信頼できる宛先 1 つには侵害アラートの 許可 を使い、マシン全体のトグルは、ほかの方法では動かないマシンにだけ使ってください。

シークレットがホスト上のどこにあるか

機密性のあるものはすべて、インストールごとの 256 ビットのマスターキーの下、AES-GCM で保管時に暗号化されます — シークレットボールトです。マスターキーは macOS の Data Protection Keychain にあり、アプリの署名 ID にスコープされ、アクセシビリティは kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly で、iCloud 同期は無効です。それはプロンプトを出さず、同期せず、Mac を離れることは決してありません。キーチェーンに到達できない場合(署名なしまたはプロビジョニングされていないビルド)、アプリは暗号文の傍らに保管されたモード 0600 のキーファイルにフォールバックします — キーと暗号文が同じディスクを共有するため弱いですが、保管時の暗号化は機能し続けます。完全にプロビジョニングされたリリースはキーチェーンを使用します。

実際上の帰結は次のとおりです。

  • バックアップとコピーは暗号文。 Time Machine のバックアップやコピーされた Application Support フォルダには、暗号化されたブロブしか含まれません。この Mac のキーチェーンエントリがなければ、それらは復号できません(ファイルフォールバックキーが使われ、一緒にコピーされていた場合を除く)。
  • キーチェーンエントリを消去するとキーがローテーションされる。 既存の暗号化されたブロブは読めなくなり、認証情報を再入力することになります。profile.json 内の機密でないメタデータは影響を受けません。
  • どこにも同期されない。 アプリ自身によって、認証情報、トークンストア、キーマテリアルがアップロード、同期、バックアップされることはありません。

ディスク上の場所は、特記なき限りすべて ~/Library/Application Support/BromureAC/ の下にあります。

場所内容
ca/cert.pem、ca/key.pemBromure Agentic Coding Root CA(キーはモード 0600)。ローテーションするにはディレクトリを削除します。
fake-salt.bin偽物の導出の背後にある、インストールごとの 32 バイトの HKDF ソルト(0600)。これを削除すると、この Mac 上のすべての偽物がローテーションされます。
claude-subscription.enc、codex-subscription.enc、grok-subscription.enc、kimi-subscription.encAES-GCM で暗号化されたサブスクリプションの保存領域:共有のサインインと、各マシン独自のサインイン。0600。
models.enc環境設定 › モデル のグローバルなモデル設定。プロバイダーの API キーを含み、保管庫の鍵で暗号化されます。
pii/<workspace-id>.key個人データ保護の代替値の元になるマシンごとの鍵(0600)。
secrets-master.key0600 のフォールバックマスターキー — Data Protection Keychain に到達できない場合にのみ存在します。
default-ssh/id_ed25519.raw、default-ssh/id_ed25519.pub新しいマシンにコピーされる、共有の既定の SSH 鍵ペア。
profiles/<id>/ssh/マシンごとに発行された SSH 鍵(エージェントのディレクトリ)。
Keychain: io.bromure.agentic-coding.master-keyAES-256 ボールトマスターキー(アカウント v1)、Data Protection Keychain。
Keychain: io.bromure.agentic-coding.ssh-key-passphrasesインポートされた SSH キーのパスフレーズ、プロファイル/キーファイルごとに 1 アイテム。

インポート用のホスト側の読み取り — ~/.aws/config、~/.aws/sso/cache/*.json、~/.docker/config.json、kubeconfig ファイル — はホスト上でのみ起こります。それらのファイルのいずれも VM にマウントされることは決してありません。暗号化されたトレースボディ(トレースを参照)は、同じボールトキーを使用します。

境界を自分で検証する

ワイヤ境界は、信頼で受け入れるのではなく、確認できるように設計されています。任意のセッション内のシェルから、次のようにします。

1. 環境は偽物を保持している。

echo "$ANTHROPIC_API_KEY"
# sk-ant-api03-brm-…            ← a fake, not your key

env | grep -E 'TOKEN|KEY' 
# every value is brm_/ghp_/glpat_/dop_v1_/lin_api_-shaped placeholder

2. 設定ファイルは偽物を保持している。

cat ~/.git-credentials          # fake tokens per git host
cat ~/.docker/config.json       # fake base64 auth blobs
grep -A2 credential_process ~/.aws/config   # helper, not a secret key

3. それでもすべてが機能する。

aws sts get-caller-identity     # succeeds — the host resigned the request
gh api user                     # succeeds — the fake was swapped on the wire

4. VM 内の TLS はプロキシで終端する。

openssl s_client -connect api.anthropic.com:443 -brief 2>&1 | head
# issuer: the Bromure Agentic Coding Root CA — not a public CA

5. SSH キーは存在しないが、署名は機能する。

ssh-add -L                      # lists public keys served by the vsock agent
ls ~/.ssh/id_*                  # no private key files to find

6. ホストで差し替えが起きるのを確認する。 セキュリティ タイムラインを開き、資格情報ブローカー で絞り込みます。差し替えのたびに、sk-a…f9q3 → api.anthropic.com — swapped in … のような行が表示されます。マシンでトレースを有効にしていれば、次のコマンドも実行できます。

bromure-cli trace summary        # per-request swap reports and leak warnings
bromure-cli trace leaks          # only the suspicious ones

またはトレースインスペクタ(⇧⌘I)を開くと、差し替えられたリクエストには Never sent to VM — swapped by proxy と注釈が付きます。

もし VM 内で本物の認証情報を見つけたなら、それは 2 つの経路のいずれかでそこに至ったものです。あなた(またはあなたの指示によるエージェント)が手作業で貼り付けたか、共有フォルダを経由して届いたかです。差し替えの仕組みが本物をゲストに書き込むことは決してありません — そして侵害検出器がワイヤ上の本物の形状のシークレットを漏洩として扱うのは、まさにそれらがそこに存在すべきではないからです。

クイックリファレンス

ゲスト・ホスト境界上の vsock ポート:

ポート目的
8443HTTPS MITM プロキシ — ゲストの egress のすべて。
8444SSH_AUTH_SOCK の背後にある ssh-agent ブリッジ。
8445AWS credential_process ヘルパー。
8446登録用 VM が使う Claude のトークンチャネル――ローカル推論のブリッジと共有しているポートです(両者は別々のフローで設定されます。モデルとプロバイダーを参照)。
8447登録用 VM が使う Codex のトークンチャネル(アクセストークン、リフレッシュトークン、ID トークン)。

どちらのトークンチャネルも一方向です。ホストは VM にダミーを書き込むことしかできず、VM はホストに本物の値を送ることしかできません。VM が本物のトークンを要求して取り戻すリクエストは存在しません。

関連する CLI コマンド(完全なリファレンスは CLI、API、MCP):

コマンド目的
bromure-cli workspaces create --auth token|subscription|bedrock|localプライマリエージェントの認証モードを指定してワークスペースを作成します。
bromure-cli vm run --auth token|subscription|bedrock|localその場で作るワークスペースの認証モードを選んで VM を起動します。
bromure-cli workspaces ssh-keygen <workspace>新鮮なワークスペース SSH キーをホスト側で発行し、公開鍵を出力します。
bromure-cli trace summary [workspace]差し替えと漏洩警告を含む、トレースされたトラフィックを要約します。
bromure-cli trace leaks [workspace]認証情報の漏洩の可能性があるトレースされたリクエストを表示します。