憑證與傳輸邊界
一個代理式編碼工作階段需要憑證——用來與 Claude 對話的 Anthropic 金鑰、用來推送的 GitHub 權杖、用來部署的 AWS 金鑰。它同時也會執行任意程式碼、安裝任意套件,並遵循它並未撰寫的檔案中的指示。把你真正的密鑰交給這樣的環境,正是金鑰最終落入竊取者收件匣的原因。
Bromure Agentic Coding 以傳輸邊界化解這個矛盾:VM 內部的代理程式永遠只會看見偽造的佔位權杖。你真正的憑證以加密形式存放在 macOS 主機上,並由主機端的 MITM 代理伺服器在最後一刻——在請求離開 VM 之後、且僅當請求送往該憑證所屬的主機時——替換到傳輸線路上。VM 內部沒有任何檔案、環境變數或行程會包含真正的 API 金鑰、OAuth 權杖、AWS 密鑰或 SSH 私鑰。
本章從頭到尾說明此機制,接著逐一介紹每一種支援的憑證類型與其生命週期、每次使用的核准系統、入侵偵測器,以及你如何自行驗證此邊界。
附註: 本章涵蓋概念與執行階段行為。如需設定窗格的逐欄位參考,請見設定 → 憑證。
傳輸邊界一覽
三項原則定義了此模型:
- VM 內是偽造值。 你設定的每一個憑證,在 VM 內部都會被一個保留結構的偽造值取代。偽造值維持驗證器所預期的形狀——Anthropic 偽造值以
sk-ant-api03-brm-開頭,GitHub 偽造值是ghp_加上 36 個字元——因此像claude、gh和doctl這類工具都會毫無異議地接受它們。 - 真值只存在於傳輸線路上。 VM 發出的每一個 HTTPS 請求都會通道傳送到主機代理伺服器,由它解密、將偽造值換成真值,再重新加密後往上游傳送。此替換的範圍侷限於該憑證所產生的目的地主機。
- 失敗即封閉。 如果有任何東西繞過了代理伺服器,該請求只會攜帶偽造值,上游驗證便會失敗。不存在任何會意外洩漏真正密鑰的路徑。
偽造值是確定性的:每一個偽造值都是透過 HKDF-SHA256,從真值加上一個各安裝專屬的 32 位元組鹽值衍生而來。同一把真正的金鑰在你的 Mac 上永遠對應到同一個偽造值,因此那些會對其金鑰做指紋辨識的用戶端(例如 Claude Code 會快取金鑰雜湊)永遠不會看到憑證在各工作階段之間「輪替」。
| 憑證 | VM 內的偽造值形狀 |
|---|---|
| Anthropic API 金鑰 | sk-ant-api03-brm-… |
| OpenAI API 金鑰 | sk-brm-… |
| xAI API 金鑰 | xai-brm-… |
| GitHub 權杖 | ghp_ + 36 個字元(共 40 個) |
| GitLab 權杖 | glpat- + 20 個字元 |
| DigitalOcean PAT | dop_v1_ + 十六進位(共 64 個字元) |
| Linear API 金鑰 | lin_api_ + 40 個字元(共 48 個) |
| MCP bearer 權杖 | brm-mcp_… |
| Docker 登錄密碼 | brm-docker-…(至少 40 個字元) |
| Kubernetes bearer 權杖 | brm-k8s-… |
| 資料庫密鑰 | brm-db-…(至少 32 個字元) |
| 通用手動權杖 | brm_… |
此邊界並沒有開關。代理伺服器是 VM 唯一的出口路徑;替換就是本應用程式中憑證運作的方式。
替換如何從頭到尾運作
一個經過驗證的請求的完整往返:
- 工作階段啟動——權杖計畫。 當一個工作區 VM 啟動時,應用程式會建立一份各工作區專屬的權杖計畫,將每一個真正的憑證與其衍生的偽造值配對。偽造值會被寫入 VM:環境變數(
ANTHROPIC_API_KEY、GH_TOKEN、LINEAR_API_KEY、…)與設定檔(~/.git-credentials、~/.docker/config.json、~/.kube/config、~/.aws/config、~/.config/doctl/config.yaml、MCP 設定)。真值則被載入代理伺服器記憶體中的替換對應表,每一項都以其所屬的目的地主機為鍵。 - 請求離開 VM。 客體的 HTTPS 流量透過一個 virtio socket(vsock 連接埠 8443)通道傳送到主機代理伺服器。VM 沒有其他通往網路的路由。
- TLS 終止。 代理伺服器出示一張偽造的各主機專屬葉憑證——以目的地主機名稱作為 CN 與 SAN、一把各主機專屬的 EC 金鑰——由 Bromure Agentic Coding Root CA 簽署。由於該 CA 的公開憑證在開機時就已安裝進 VM 的信任存放區,客體的 TLS 用戶端便會接受此連線,代理伺服器也就能讀取明文請求。
- 替換。 代理伺服器查找請求中出現的每一個偽造權杖(標頭,以及對於選擇加入的憑證類型還包括本文),若目的地主機符合該憑證的範圍,便將其替換為真值。
- 往上游重新加密。 改寫後的請求透過 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 的信任存放區(透過 meta 共用傳遞,並以
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 身分(一個寫入 VM 中 ~/.gitconfig 的名稱與電子郵件;兩者都留白即可保留 git 的預設值——那些佔位文字只是範例,並非憑證),接著是一份僅列出你已設定憑證的清單,並歸類於類別標題之下(代理程式、Git、雲端、資料庫、SSH、其他)。底部有兩個按鈕:新增憑證會開啟一個憑證類型的挑選器——Git 權杖、SSH 金鑰、AWS 憑證、DigitalOcean 權杖、Linear API 金鑰、Kubernetes、容器登錄、資料庫,以及其他 API 金鑰——而匯入 env 檔…會從一個 .env 或 ~/.bashrc 批次匯入。主要代理程式本身的金鑰位於代理程式窗格,將於接下來說明。按一下儲存;下次工作階段啟動時會將偽造值寫入 VM,並將真值載入代理伺服器。
各憑證的核准閘門(使用前先詢問)與各服務的寫入原則是在防護欄窗格中設定,而非在此處——憑證窗格已不再承載那些控制項。逐欄位參考請見設定 → 憑證。
有六個供應者是自動處理的——Anthropic、OpenAI、GitHub、GitLab、DigitalOcean 與 Kubernetes 都不需要手動權杖規則;它們各自的專屬章節會涵蓋。其餘一切都透過其他 API 金鑰處理。
從 env 檔匯入。 匯入 env 檔…會讀取一個現有的 .env 檔——或一個 ~/.bashrc——並將其變數轉換為憑證。解析器可處理 KEY=VALUE 與 export KEY=VALUE,會剝除包圍的引號與尾端註解,並刻意略過任何需要 shell 求值的內容($VAR 內插或 $(…) 替換),因此指向一個真實的 .bashrc 是安全的。接著一張審查表單會以遮罩過的值顯示這些變數:已知名稱(ANTHROPIC_API_KEY、OPENAI_API_KEY、XAI_API_KEY、GH_TOKEN/GITHUB_TOKEN、GITLAB_TOKEN、AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN、DIGITALOCEAN_ACCESS_TOKEN、LINEAR_API_KEY)會自動對應到其憑證類型,而未知名稱則可以你提供的逗號分隔主機範圍匯入為通用手動權杖。已設定的項目會被標示並保持未勾選,因此重新匯入絕不會靜默地覆蓋掉某個密鑰。
憑證類型
主要代理程式 API 金鑰(Anthropic、OpenAI、xAI)
工作區主要代理程式的金鑰是在代理程式窗格中設定,該處每張代理程式卡片都提供一個驗證模式選擇器。
選擇 API 權杖並將金鑰貼入欄位(Claude Code 用 Anthropic API 金鑰、Codex 用 OpenAI API 金鑰、Grok Build 用 xAI 金鑰)。生命週期:
- 在 VM 中: 匯出為
ANTHROPIC_API_KEY/OPENAI_API_KEY/XAI_API_KEY,持有供應者形狀的偽造值(sk-ant-api03-brm-…、sk-brm-…、xai-brm-…)。 - 在傳輸線路上: 對送往該供應者主機(分別為
anthropic.com、openai.com、x.ai)的請求,替換為真正的金鑰。 - 核准: 若要為每個工作階段的首次使用設閘門,請在防護欄窗格中為該代理程式的金鑰開啟使用前先詢問(見每次使用核准)。此項預設為關閉。
選擇器上的其他驗證模式——訂閱(互動式登入)、Bedrock(AWS)與本機模型——將於下方及本機模型中涵蓋。從 CLI 來看,同樣的選擇是 bromure-cli workspaces create 上的 --auth token|subscription|bedrock|local(以及即時工作區的 bromure-cli vm run 上的 token|subscription|bedrock)。
Claude、Codex 與 Grok 訂閱
如果你擁有的是 Claude、ChatGPT(Codex)或 Grok 訂閱而非 API 金鑰,代理程式通常會透過互動式 OAuth 登入來驗證——這是一段瀏覽器流程,一個沙箱化的 VM 無法(也不應該)以真正的權杖完成。Bromure Agentic Coding 以兩種機制支援訂閱。兩者最終都殊途同歸:真正的 OAuth 權杖只存在於主機上,客體則以一把假金鑰執行。
向 Claude / ChatGPT / Grok 註冊(建議)
將代理程式的驗證模式設為訂閱(互動式登入),並按一下註冊…。接下來會發生的事:
- 應用程式會檢查代理伺服器是否正在執行(否則會拒絕註冊),並顯示一張標題為向 Claude 註冊(或 ChatGPT / Grok)的說明表單。按一下「繼續」。
- 一個用完即棄的註冊 VM會開機——臨時、隔離,沒有掛載工作區資料夾,也沒有憑證替換對應表。在其內部會執行真正的登入指令(
claude login、codex login,或 Grok 的對應指令)。 - 你 Mac 的預設瀏覽器會開啟該供應者的登入頁面。如常登入。你大約有 4 分鐘的時間,之後流程便會逾時。
- 產生的 OAuth 權杖會在主機上被擷取、加密並儲存;用完即棄的 VM 隨即銷毀。
- 若你是從工作區編輯器啟動註冊,應用程式會詢問與每個工作區共用嗎?——選擇每個工作區將訂閱儲存為共用預設值,或選擇僅此工作區。從應用程式偏好設定啟動的註冊一律不詢問,直接儲存為共用預設值。
此後,每個工作階段的客體都以 API 金鑰模式搭配一個確定性的假憑證執行——Claude 用一個偽造的 ANTHROPIC_API_KEY、Codex 用一個植入的 ~/.codex/auth.json(內含一個偽造且效期為遙遠未來的 JWT,如此用戶端便絕不會自行嘗試刷新它)、Grok 用一個佔位的 ~/.grok/auth.json。代理伺服器辨識出該假值,並在傳輸線路上注入一個有效的 Authorization: Bearer 存取權杖(Claude 還會加上 OAuth beta 標頭)。
權杖保管與刷新完全在主機端進行。主機會在到期前約 5 分鐘,向供應者的權杖端點(Claude 為 platform.claude.com/v1/oauth/token、Codex 為 auth.openai.com/oauth/token、Grok 為 auth.x.ai/oauth2/token)刷新權杖,因此一次刷新即可服務每一個執行中的 VM,而客體從不持有刷新權杖。一筆剛擷取的記錄會刻意以一個已經過去的到期時間儲存,強制在首次使用時刷新——在你依賴它之前就先證明刷新路徑可運作。
驗證模式選擇器旁的控制項可完成整個生命週期:重新註冊…會重複擷取(例如在上游撤銷工作階段之後),而忘記則會從主機刪除已儲存的訂閱。
工作階段內的權杖替換
或者,如果代理程式自己在 VM 內部登入(你在工作階段中執行 claude login),代理伺服器會注意到一個真正的訂閱 OAuth 權杖正往供應者送出,並提議接管它。此時會出現一張表單——替換 Claude 訂閱權杖?(或 Codex)——說明真正的權杖可以留在這台 Mac 上,同時由一個偽造值取代 VM 憑證檔中的它。存取權杖與刷新權杖會一併替換。你的選項:
| 按鈕 | 效果 |
|---|---|
| 替換 | 真正的權杖移入主機存放區;VM 的憑證檔以偽造值改寫;代理伺服器從此在傳輸線路上注入真正的權杖。 |
| 暫時不要 | 本工作階段不做任何變更;此提示會在下個工作階段再次出現。 |
| 此工作區永不 | 停止此工作區的提示。 |
此提示背後的各工作區狀態,會在編輯器中顯示為 Claude 訂閱權杖替換 / Codex 訂閱權杖替換(預設為未設定;在你選擇之後顯示為「已接受」或「已拒絕」)。主機對 VM 的替換通道刻意是單向的:主機只能將偽造值寫入 VM,而 VM 只能將真值送出至主機——沒有任何 RPC 能讓 VM 索回一個真正的權杖。VM 內的代理程式還會拒絕寫入任何不帶有 brm- 偽造前綴的憑證,因此即使是一個行為不當的主機,也無法用真值汙染客體的憑證檔。
附註: Codex 在客體內部仍維持訂閱模式(其 API 金鑰模式指向不同的後端),而 Grok 的權杖是透過檔案
~/.grok/auth.json傳輸,而非透過 vsock 代理程式。這些都是實作細節;保管模型是相同的。
AWS
AWS 獲得所有供應者中最深入的處理,因為 AWS 請求並非以 bearer 權杖驗證——它們是被簽署的(SigV4)。在工作區編輯器中開啟憑證 → AWS;一個分段控制項可在靜態金鑰與 SSO / Identity Center 之間選擇。
靜態金鑰與主機重簽署器
貼上你的存取金鑰 ID 與密鑰(外加一個選用的 STS 工作階段權杖與一個預設區域)。生命週期:
- 在 VM 中:
~/.aws/config指向一個 credential_process 輔助程式,它會——透過 vsock 連接埠 8445——提供真正的存取金鑰 ID,搭配一個 40 個字元的偽造密鑰,並省略工作階段權杖。每一個 AWS SDK、awsCLI、terraform 與 boto3 都會原生地採用它;不需要任何工具專屬的設定。 - 客體所做的事: 以偽造的密鑰簽署其請求,產生一個語法上有效但密碼學上註定失敗的 SigV4 簽章。
- 在傳輸線路上: 主機的 AWS 重簽署器會偵測送往
*.amazonaws.com與*.amazonaws.com.cn的請求(包含 GovCloud、ISO、區域性與 bucket 樣式的 S3 主機),剝除客體的簽章,在存在工作階段權杖時注入真正的X-Amz-Security-Token,並在請求離開你的 Mac 之前以真正的密鑰重新簽署。每一次成功的重簽署都會發出一個帶有遮罩過存取金鑰的credential.aws_sign稽核事件,可在追蹤中看見。
這在最強的意義上是失敗封閉的:真正的密鑰以任何形式都從不存在於 VM 中,而一個繞過代理伺服器的請求會被 AWS 以 InvalidSignatureException 拒絕。
有三種請求樣式不受支援,會向客體回傳一個明確的錯誤而非靜默失敗:分塊串流 S3 上傳(STREAMING-AWS4-HMAC-SHA256-PAYLOAD,以 501 回應)、SigV4A 非對稱簽署,以及預簽署的查詢字串 URL(它們將簽章嵌入重簽署器無法替換之處)。
SSO / IAM Identity Center
如果你的組織使用 IAM Identity Center,請選擇 SSO / Identity Center 而非貼上長效金鑰:
- 按一下授予對 ~/.aws 的存取權並核准資料夾存取提示(一項安全範圍界定的授權;該資料夾是在主機上讀取,絕不掛載進 VM)。
- 從 SSO 設定檔挑選器中挑選你的設定檔。應用程式會探索
~/.aws/config中帶有sso_start_url、sso_account_id與sso_role_name的[profile …]區段,並解析[sso-session …]參照;帳戶 ID 與角色以唯讀方式顯示。 - 在工作階段啟動時,主機會從 SSO 權杖快取(
~/.aws/sso/cache)解析暫時性角色憑證。若快取的權杖已過期,你的瀏覽器會開啟以進行aws sso login——在主機上,從/usr/local/bin/aws執行。
解析出的暫時性金鑰饋入與靜態金鑰相同的重簽署器;VM 仍舊從不看見密鑰。憑證會在主機上於到期前約 5 分鐘自動刷新。
Bedrock
代理程式驗證模式選擇器上的 Bedrock(AWS)會使用工作區所設定的任何 AWS 憑證(靜態或 SSO),以 AWS Bedrock 執行 Claude Code——它是主要工具的一種驗證模式,而非另一種獨立憑證。設定驗證模式、設定憑證 → AWS,並選擇性地在工作區上設定一個 Bedrock 模型 ID。簽署會走與其相同的重簽署器路徑,因為 Bedrock 端點是 *.amazonaws.com 主機。
Git HTTPS 權杖(GitHub、GitLab、Bitbucket、自架)
用於 git-over-HTTPS 的個人存取權杖位於 GitHub 權杖 / GitLab 權杖 / Bitbucket 權杖(統稱為 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 權杖替換呈現)之下新增一項項目。按一下新增權杖並提供:
| 欄位 | 意義 |
|---|---|
| 名稱 | 該項目的標籤。 |
| 值 | 真正的密鑰(以加密形式存放在主機上)。 |
| 環境變數名稱 | 偽造值在 VM 內部匯出時所用的變數。從你的程式碼中參照它。 |
| 主機篩選(選用) | 該替換的主機範圍。 |
有兩種邊界情況是刻意設計的:
- 空的環境變數名稱: 不匯出任何東西;你從工作階段的歡迎橫幅複製偽造值,並將它放到你的工具所需之處。
- 空白的主機篩選: 真值會在任何主機上注入,不加詢問。這是一個明確的永遠開啟選擇——對於有許多區域性主機名稱的 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,編輯器會顯示一個取得 1Password CLI 連結,且工作區會在啟動時呈現安裝說明;如果解析失敗(未登入,或項目不存在),Bromure 會呈現該錯誤,好讓你修正並重新啟動工作區。
匯入一個 .env 或 .env.op 檔(編輯器中的從 .env 匯入…)會自動辨識 op:// 值——無論是在 ANTHROPIC_API_KEY 這類已知名稱下,還是 STRIPE_KEY 這類任意名稱下——並將每一個儲存為持有該參照的手動權杖。
DigitalOcean
在憑證 → DigitalOcean 之下貼上一個個人存取權杖(在瀏覽器中開啟 DigitalOcean 權杖頁面連結會帶你前往權杖產生頁)。偽造值(dop_v1_ + 十六進位,64 個字元)會匯出為 DIGITALOCEAN_ACCESS_TOKEN 並寫入 ~/.config/doctl/config.yaml,因此不需要 doctl auth init。此替換涵蓋送往 digitalocean.com 的請求,外加第二項項目,用於 docker login / doctl registry login 對 registry.digitalocean.com 所使用的 base64 Basic-auth 區塊,如此登錄的推送與提取也能解析。
Linear
在憑證 → Linear 之下貼上一個個人 API 金鑰(連結:在瀏覽器中開啟 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 議題自動化觸發器的先決條件——見自動化與 CLI。
MCP 伺服器 bearer 權杖
在 MCP 窗格中設定的 HTTP 傳輸 MCP 伺服器會獲得相同的處理:真正的 bearer 權杖留在主機上,一個 brm-mcp_… 偽造值被注入代理程式所讀取的 MCP 設定中,代理伺服器則在傳輸線路上替換它,範圍界定為該伺服器的主機。只有已啟用、且 bearer 權杖非空的 HTTP 傳輸伺服器才會獲得一筆替換項目。
還有一項額外的貼心處理:對於帶有 brm-mcp_ 項目的主機,代理伺服器會以 404 回應 OAuth/OIDC 探索路徑(.well-known authorization-server、protected-resource 與 OpenID configuration 端點)。Claude Code 於是將該伺服器視為已預先驗證,而非嘗試其自己的 OAuth 流程——反正該流程在 VM 內部也永遠無法完成。
容器登錄(Docker Hub、GHCR 及其同類)
憑證 → 容器登錄管理用於 docker pull/push 的 HTTP Basic 驗證。已有 Docker Hub(docker.io)、GitHub Container Registry(ghcr.io)與 GitLab Container Registry(registry.gitlab.com)的預設值;任何其他登錄都可以依主機新增。生命週期:
- 在 VM 中:
~/.docker/config.json包含一個偽造的驗證區塊——你的使用者名稱搭配一個衍生的brm-docker-…密碼的 base64——如此 Docker 便相信它已登入。 - 在傳輸線路上: 代理伺服器在相符的登錄主機上替換真正的 base64 區塊。distribution-spec 的權杖交換也會處理:會為已知的驗證領域新增替換項目(Docker Hub 對
auth.docker.io驗證,DigitalOcean 的登錄對api.digitalocean.com驗證)。 - 匯入: 按一下匯入 config.json…,從主機上一個現有的
~/.docker/config.json拉取項目。委派給credsStore/credHelpers的項目會被略過——它們的密碼存放在作業系統的鑰匙圈中,而非檔案裡——匯入摘要會回報略過了多少個以及原因。 - 核准: 依登錄,透過防護欄窗格中的使用前先詢問。移除此登錄會刪除一項項目。
Kubernetes 環境定義
憑證 → Kubernetes 將 kubeconfig 環境定義轉為由代理伺服器中介的叢集存取。按一下匯入 kubeconfig將一個現有的 kubeconfig 剖析為每個環境定義一列(current-context 排在最前,驗證類型自動偵測),或按一下新增環境定義手動輸入伺服器 URL、憑證、命名空間與叢集 CA。無論何種情況,VM 都會收到一份合成的 ~/.kube/config:客體中的 kubectl 是與代理伺服器(透過 Bromure CA 信任)對話,絕不直接與 API 伺服器對話。
依驗證類型:
- Bearer 權杖環境定義在 VM 中獲得一個
brm-k8s-…佔位值,在傳輸線路上替換為真正的權杖。 - 用戶端憑證環境定義在 VM 中獲得一張用完即棄的自簽憑證與金鑰;真正的憑證與金鑰在主機上註冊為一個
SecIdentity,並用於上游 mTLS。 - Exec 外掛程式環境定義根本從不在 VM 中執行該外掛程式。exec 外掛程式輪詢器會在主機上於每個刷新間隔(預設 600 秒,下限 60)執行該指令,剖析
ExecCredentialJSON,並將新鮮的權杖饋入替換對應表。刷新會保留該項目的同意狀態。
如果 kubeconfig 提供了叢集自己的 CA,它會被轉送,好讓代理伺服器能驗證上游 API 伺服器。匯入的 kubeconfig 中的檔案路徑欄位(CA、憑證、金鑰)會在匯入時急切讀取——之後對那些磁碟上檔案的變更不會被採納。每個環境定義在防護欄窗格中都有自己的使用前先詢問列,在那裡一項寫入原則還可以在任何位元組被轉送之前,於主機端剝除具破壞性的動詞(kubectl delete、AWS Delete*/Terminate*、docker push、git push)——這是與憑證替換分開的一層。
HTTP 資料庫(MongoDB、ClickHouse、Elasticsearch)
憑證 → 資料庫(MongoDB / ClickHouse / Elasticsearch 區段)涵蓋以 HTTPS 溝通的資料庫端點——Mongo Data API、ClickHouse 的 HTTP 介面、Elastic。每一個端點需要一個引擎、主機、密鑰、使用者名稱、驗證類型,以及一個或多個環境變數名稱(以逗號分隔),brm-db-… 偽造值會在這些名稱下匯出;從你的程式碼或連線字串中參照那些變數。
資料庫憑證是唯一一個替換會同時掃描請求本文以及標頭與查詢參數的家族,因為連線密鑰經常夾帶在 JSON 或 SQL 酬載內部。代理伺服器會在本文替換後修補 Content-Length;其他流量中無關的 multipart 或二進位本文絕不會被觸碰(所有其他替換都僅限標頭)。Basic-auth 端點也會替換其 base64 的使用者與密鑰區塊。各端點的使用前先詢問與寫入原則是在防護欄窗格中設定。
SSH 金鑰
SSH 是在完全不用任何權杖的情況下處理的:VM 的 SSH_AUTH_SOCK 由一個透過 vsock(連接埠 8444)的 ssh-agent 橋接器支援。客體可以列出身分並請求簽章,但私鑰的位元組只存在於主機上,並且在物理上無法從 VM 內部讀取或擷取。存在兩個金鑰來源,兩者都在憑證 → SSH 金鑰之下:
- 各工作區的預設金鑰。 一把共用的預設 ed25519 金鑰對會在應用程式啟動時產生(存放於 Application Support 中的
default-ssh/之下),並複製到每個新工作區的代理程式目錄。此窗格會顯示該工作區的公鑰,好讓你將它貼入你的 git 主機(GitHub 為 github.com/settings/keys)。你也可以從 CLI 以bromure-cli workspaces ssh-keygen <workspace-id|name>產生一把新鮮的金鑰,它會印出新的公鑰。 - 匯入的金鑰。 在匯入的 SSH 金鑰之下按一下匯入… / 匯入檔案…,並將應用程式指向一個現有的私鑰檔——支援 RSA、ed25519 與 ECDSA,包括加密的金鑰。加密的金鑰會在匯入時提示輸入其複雜密碼一次;該複雜密碼儲存在 macOS 鑰匙圈中(服務
io.bromure.agentic-coding.ssh-key-passphrases),並在啟動時透過SSH_ASKPASS提供,絕不記錄。匯入金鑰的簽署流程會通過應用程式為自己衍生的一個私有 ssh-agent 行程(在暫存目錄下某個 socket 上的ssh-agent -D)——與你系統上的其他任何東西分開。
對於每一把匯入的金鑰,在防護欄窗格中開啟使用前先詢問,會讓每一個 VM 內的簽章請求都提示徵求同意。每一個簽章——無論是預設或匯入的金鑰——都會發出一個 credential.ssh_sign 稽核事件,攜帶該金鑰的 SHA256 指紋以及它是受管理還是匯入的金鑰。
附註: 你的 macOS 登入 ssh-agent(launchd 那個)刻意絕不暴露給 VM。只有各工作區的金鑰以及你明確匯入的金鑰才能從一個工作階段觸及。
每次使用核准與授權期限
本章中的任何憑證都可以被標示為使用前先詢問——這是防護欄窗格中一個各憑證專屬的核取方塊(在控制項本身上標示為需要核准才能使用),預設關閉,在 UI 中描述為:「在某個工作階段中首次使用此憑證時彈出一個確認對話方塊。」
當一個設有閘門的憑證在某個工作階段中首次被使用時,代理伺服器會保留該請求並顯示一個標題為**允許「工作區名稱」使用憑證?**的同意對話方塊(其中填入你工作區的名稱與該憑證的標籤),提供四個按鈕:
| 按鈕 | 授權 |
|---|---|
| 允許 5 分鐘 | 有時限;該憑證會在 5 分鐘內順暢流通而不再提示。 |
| 允許 1 小時 | 有時限,1 小時。 |
| 允許本工作階段剩餘時間 | 直到工作階段視窗關閉為止。 |
| 不允許 | 該請求被拒絕;此拒絕會被記住 5 分鐘,好讓一場代理程式的重試風暴不會產生一場對話方塊風暴。 |
值得了解的行為:
- 合併。 需要同一個憑證的並行請求會合併到一個對話方塊上——一個話多的代理程式發出十二個平行 API 呼叫只會產生一個提示,而這十二個全都會遵循你的決定。
- 拒絕優先。 一個生效中的拒絕會在任何較舊的允許被查閱之前就短路。
- 依設計即短暫。 授權與拒絕僅保存在記憶體中,並在工作階段拆除時撤銷。「本工作階段剩餘時間」永遠不會在視窗關閉後存活,且沒有任何東西會在應用程式各次執行之間持續保存。
- 無介面工作階段。 在一個 SSH 或無介面工作階段中,該提示會出現在工作區的 tmux 中,而非作為一個 GUI 警示——見遠端存取。
對於 AWS,此閘門適用於每一次主機端的簽署呼叫;對於 SSH 金鑰,適用於簽章請求;對於其他一切,適用於該工作階段的第一次傳輸線路替換。
提示: 此同意閘門是依憑證而非依主機。如果你想讓一個未界定範圍的手動權杖維持在控制之下,核准正是為它設計的機制。
憑證核准視窗
視窗 → 憑證核准…會開啟一個即時檢視,顯示目前應用程式執行期間所做的每一個同意決定:有時限的允許(5 分鐘 / 1 小時 / 工作階段剩餘時間)與被記住的拒絕。每一列顯示工作區名稱與剩餘時間,並提供撤銷;全部撤銷(⌘⌫)可一次清除所有內容。此清單每 2 秒自動重新整理,並隨著授權到期而自然縮減。
由於決定僅存在於記憶體中,此視窗在授權到期後、工作階段關閉後(工作階段範圍的授權)以及應用程式結束後便為空。它是一個當下的控制面板,而非稽核記錄——若要查看歷史,請使用追蹤。
入侵偵測器
這些偽造值身兼二職:除了代替密鑰之外,它們還是絆索。一個偽造權杖只有一個正當的目的地家族——它所產生的主機範圍。沒有任何誠實的理由讓 sk-ant-api03-brm-… 出現在一個送往 pastebin.example 的請求中。因此代理伺服器會掃描每一個外送請求——標頭與本文,透過一個 Aho-Corasick 自動機,其成本低廉到足以在所有東西上執行——尋找任何前往其範圍之外的偽造值。
當它找到一個時,便將該請求視為企圖進行的憑證外洩:
- 該請求被以 HTTP 451 封鎖。連一個位元組都不會被轉送到目的地。
- VM 立即被暫停。
- 一則警示觸發:「Bromure 偵測到一個外送嘗試,欲將一個工作階段憑證洩漏給一個並非為它產生的主機。該 VM 已被暫停。」
該工作區隨即被標示為已入侵——工作區瀏覽器會顯示已入侵——啟動時將提示清除磁碟與家目錄——而下次啟動需要修復:*「若要繼續,必須清除 VM 磁碟映像檔與持續性家目錄資料夾。你的權杖、ssh 金鑰與工作區設定都會保留。」*按一下清除並啟動以繼續。留意隨附的警告:共用資料夾不會被清除,因此如果入侵是透過共用資料夾中的某個套件或檔案而來,它可能仍在那裡——在恢復工作之前先審查那些資料夾。
對一則入侵警示的建議回應:開啟追蹤檢視器(⇧⌘I)或執行 bromure-cli trace leaks 以查看違規的主機與請求,判斷是某個專案相依項還是一條提示注入的指示要負責(見提示注入與供應鏈),然後清除並重新啟動。
範圍細節:
- 未界定範圍的偽造值可豁免。 一個帶有空白主機篩選的手動權杖依設計就是「任何主機」,無法觸發偵測器;假的訂閱佔位值同樣也被排除在外。
- 第一方的手足可容忍。 比對會鏡像替換的範圍原則,只放寬一項:與該憑證供應者位於同一個註冊網域下的主機(例如
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,而傳輸邊界的存在正是為了讓這件事變得不必要。
沒有任何東西需要啟用——偵測器一律開啟。
密鑰在主機上存放於何處
一切敏感的東西都以 AES-GCM 在一把各安裝專屬的 256 位元主金鑰下靜態加密——即密鑰保險庫。主金鑰存放於 macOS 的 Data Protection Keychain,範圍界定至應用程式的簽署身分,其可存取性為 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,且 iCloud 同步已停用。它從不提示、從不同步,也從不離開 Mac。如果鑰匙圈無法觸及(一個未簽署或未佈建的組建),應用程式會退回到一個模式為 0600、存放在密文旁邊的金鑰檔——較弱,因為金鑰與密文於是共享一個磁碟,但它仍讓靜態加密持續運作;一個完全佈建的正式版本會使用鑰匙圈。
實務後果:
- 備份與副本都是密文。 一份 Time Machine 備份或一個複製的
Application Support資料夾只包含加密的區塊;沒有這台 Mac 的鑰匙圈項目便無法解密它們(除非當時使用的是檔案退回金鑰,且一併被複製)。 - 清除鑰匙圈項目會輪替金鑰。 現有的加密區塊會變得無法讀取,而你需要重新輸入你的憑證。
profile.json中的非敏感中繼資料不受影響。 - 沒有任何東西同步到任何地方。 應用程式本身不會上傳、同步或備份任何憑證、權杖存放區或金鑰材料。
磁碟上的位置,除非另有說明,全都在 ~/Library/Application Support/BromureAC/ 之下:
| 位置 | 內容 |
|---|---|
ca/cert.pem、ca/key.pem | Bromure Agentic Coding Root CA(金鑰模式 0600)。刪除此目錄即可輪替。 |
fake-salt.bin | 偽造值衍生背後的各安裝專屬 32 位元組 HKDF 鹽值(0600)。刪除它會輪替這台 Mac 上的每一個偽造值。 |
claude-subscription.enc、codex-subscription.enc、grok-subscription.enc | 以 AES-GCM 加密的訂閱 OAuth 存放區(共用預設值加上各設定檔覆寫),0600。 |
secrets-master.key | 0600 的退回主金鑰——僅在 Data Protection Keychain 無法觸及時存在。 |
default-ssh/id_ed25519.raw、default-ssh/id_ed25519.pub | 複製到新工作區的共用預設 SSH 金鑰對。 |
profiles/<id>/ssh/ | 各工作區產生的 SSH 金鑰(代理程式目錄)。 |
鑰匙圈:io.bromure.agentic-coding.master-key | AES-256 保險庫主金鑰(帳戶 v1),Data Protection Keychain。 |
鑰匙圈:io.bromure.agentic-coding.ssh-key-passphrases | 匯入的 SSH 金鑰複雜密碼,每個設定檔/金鑰檔一項。 |
用於匯入的主機端讀取——~/.aws/config、~/.aws/sso/cache/*.json、~/.docker/config.json、kubeconfig 檔——只在主機上發生;那些檔案沒有任何一個會被掛載進 VM。加密的追蹤本文(見追蹤)使用相同的保險庫金鑰。
自行驗證此邊界
傳輸邊界的設計是可查核的,而非要人盲信。從任何工作階段內部的一個 shell:
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. 在主機上,觀看替換發生。 為該工作區啟用追蹤,然後:
bromure-cli trace summary # per-request swap reports and leak warnings
bromure-cli trace leaks # only the suspicious ones
或開啟追蹤檢視器(⇧⌘I),其中被替換的請求會被註記為從未送至 VM——由代理伺服器替換。
如果你曾在一個 VM 內部發現一個真正的憑證,它以兩種方式之一到達那裡:你(或在你指示下的代理程式)手動貼入了它,或它是透過一個共用資料夾抵達的。替換機制從不將真值寫入客體——而入侵偵測器將傳輸線路上看起來像真值的密鑰視為洩漏,正是因為它們本不應存在於那裡。
快速參考
客體與主機邊界上的 vsock 連接埠:
| 連接埠 | 用途 |
|---|---|
| 8443 | HTTPS MITM 代理伺服器——客體的整個出口。 |
| 8444 | SSH_AUTH_SOCK 背後的 ssh-agent 橋接器。 |
| 8445 | AWS credential_process 輔助程式。 |
| 8446 | Claude 訂閱權杖替換代理程式——一個它與本機推論橋接器共用的連接埠(它們是在不同的流程中設定;在診斷一個同時使用兩者的工作階段時請記住這一點——見本機模型)。 |
| 8447 | Codex 訂閱權杖替換代理程式(存取、刷新與 ID 權杖)。 |
相關的 CLI 指令(完整參考見自動化與 CLI):
| 指令 | 用途 |
|---|---|
bromure-cli workspaces create --auth token|subscription|bedrock|local | 建立一個帶有其驗證模式的工作區。 |
bromure-cli vm run --auth token|subscription|bedrock | 啟動一個 VM,為一個即時工作區選擇驗證模式。 |
bromure-cli workspaces ssh-keygen <workspace> | 在主機端產生一把新鮮的工作區 SSH 金鑰並印出公鑰。 |
bromure-cli trace summary [workspace] | 摘要已追蹤的流量,包括替換與洩漏警告。 |
bromure-cli trace leaks [workspace] | 顯示帶有潛在憑證洩漏的已追蹤請求。 |