沒有 MDM,公司的規則怎麼跑到那台筆電上:拆開 server-managed settings
那台筆電是他自己買的。公司沒有 MDM、沒有端點管理系統,IT 連 managed-settings.json 該塞到哪個路徑都推不動。可是他一開 Claude Code,Read(./.env) 就是擋著的。
這份政策是從哪裡來的?更精確一點問:它在啟動流程的哪一步到達,在它到達之前的那幾百毫秒,Claude Code 照誰的規矩在跑?
「Owner 在 claude.ai 填了一份 JSON」這句先擱著,那講的是誰按了按鈕。從 client 這一側看只有兩個動作:向 api.anthropic.com 要一份 payload,存進 ~/.claude/remote-settings.json。啟動時抓一次,session 開著的話每小時再抓一次。
骨架就這麼大。難的全在時序。
那份政策在你開機的第幾毫秒到達
抓東西要時間,而 Claude Code 不能為了等一份設定讓你盯著空畫面。文件把取捨切成兩種。
開發者在啟動時登入(第一次跑,或者剛 /logout 過),Claude Code 最多等 5 秒讓 fetch 跑完才開 session。政策及時送到,就從第一個畫面開始執行,companyAnnouncements 也會顯示在上面。
其他啟動情境,以及那 5 秒等完還沒回來,Claude Code 會先把 session 開給你,讓 fetch 在背景繼續跑。這句要讀清楚:有一小段時間,你的限制還沒生效。
fetch 失敗的話,它繼續跑、不套 server-managed settings,並在互動式 session 裡警告你沒有遠端政策。endpoint-managed settings 照樣生效,那是另一條通道。
第二次以後就有快取。快取設定在啟動時立刻生效,這是它能撐過網路失敗的原因。但有三樣不吃這一套:modelPricing、managedMcpServers,還有「等伺服器確認才放行的環境變數」。
前兩樣的後果很具體。modelPricing 確認回來之前,/usage 跟狀態列上的成本數字是定價表價格;managedMcpServers 則讓 Claude Code 最多等 30 秒才去連 MCP server(需 v2.1.259 或更新)。
第三樣才真正有意思。
為什麼有些值要等伺服器點頭才准用
快取裡有一批環境變數,啟動時一律不套用,文件叫它 withheld(需 v2.1.198 或更新;在那之前整個快取 env 區塊都是啟動就套下去)。清單長這樣:
| 類別 | 被扣住的變數 |
|---|---|
| Proxy 與 TLS | HTTPS_PROXY、NODE_EXTRA_CA_CERTS、mTLS 用戶端憑證變數 CLAUDE_CODE_CLIENT_CERT 與 CLAUDE_CODE_CLIENT_KEY |
| API 路由與供應商選擇 | ANTHROPIC_BASE_URL、CLAUDE_CODE_USE_BEDROCK、CLAUDE_CODE_USE_VERTEX 等供應商選擇變數、ANTHROPIC_BEDROCK_BASE_URL 等供應商端點 URL |
| 驗證憑證 | ANTHROPIC_API_KEY、ANTHROPIC_AUTH_TOKEN、CLAUDE_CODE_OAUTH_TOKEN |
| 設定目錄選擇器 | CLAUDE_CONFIG_DIR |
v2.1.223 之後又追加一批:Workload Identity Federation 變數如 ANTHROPIC_FEDERATION_RULE_ID、ANTHROPIC_PROFILE 與 ANTHROPIC_CONFIG_DIR,以及 HOME、XDG_CONFIG_HOME、APPDATA、USERPROFILE 這些作業系統目錄變數。
這批變數有個共同點:每一個都有能力改變「下一次 fetch 會打到哪裡、帶什麼憑證、讀哪個目錄」。它們如果從快取直接生效,就有機會重導、攔截、或重新驗證那個用來確認 payload 的 fetch 本身。
一個很乾淨的自我指涉問題。你請警衛照一份名單放行,名單是從門外送進來的;名單上如果寫著「以後改從側門收名單」,那送名單的路就被名單自己改掉了。從此警衛拿到的名單都是側門那邊的人給的,你再也沒辦法從正門糾正。
所以那批值要等伺服器確認過 payload(需要核准的話,等你核准過),才會在這個 session 剩下的時間套用,其餘 env 鍵照常在啟動時生效。另有三類更新連套用都要等重啟:OpenTelemetry exporter 設定、model 鍵,以及「從 env 區塊移除某個變數」。移除比新增難,設定系統裡向來如此。
要不要跳對話框,看的不一定是變數名
有些下發的設定會在互動式 session 裡要使用者明確核准,拒絕就退出。文件列了五類:
- 會執行 shell 指令的設定:
apiKeyHelper、statusLine、otelHeadersHelper - 沙箱執行檔設定:
sandbox.bwrapPath、sandbox.socatPath、sandbox.ripgrep - 沙箱網路與隔離設定:
sandbox.network.tlsTerminate、sandbox.credentials、sandbox.filesystem.disabled那一長串,只含deny規則的sandbox.credentials除外 - 需要核准的自訂環境變數
- 任何 hook 定義
v2.1.251 之前,沙箱那一類不經核准直接套用。
用 claudeMd 鍵下發的 managed CLAUDE.md 不需要核准,因為那是給 Claude 讀的指示文字,不是 Claude Code 去執行的指令(v2.1.260 之前需要)。強制啟動器那個 processWrapper 鍵推下去時,也會並列在同一個對話框上。
到這裡都還算直覺。會讓人愣一下的是環境變數那一類:要不要問,有時候比對的是值,不是變數名。
這一類的規則攤開長這樣:
| 變數 | 不用核准的值 | 其他非空值 |
|---|---|---|
四個隱私開關:CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC、DISABLE_ERROR_REPORTING、DISABLE_TELEMETRY、DO_NOT_TRACK |
truthy(1、true),只會把追蹤關掉 |
跳對話框 |
API_FORCE_IDLE_TIMEOUT |
truthy,只是把 body idle timeout 打開 | 要核准(v2.1.248 之前任何非空值都會跳) |
ENABLE_BETA_TRACING_DETAILED、OTEL_LOG_RAW_API_BODIES |
falsy(0、false) |
要核准 |
最後那一列是反過來的。
最狠的是 ANTHROPIC_CUSTOM_HEADERS。只做標記用途的標頭(像 Accept-Language)不用核准,點名憑證、org/tenant 選擇器、路由或 host 覆寫、API 行為標頭(Authorization、X-Api-Key、Host、anthropic-beta、X-Amzn-Bedrock-*)則要核准。比對看的是標頭名稱裡出現了哪些字,所以 X-Client-Version 含了 client 跟 version,照樣要你按一次。v2.1.251 之前,這個變數不管給什麼值都不用核准。
代價是誤報。但這個位置擋的是「誰在冒充誰發請求」,寧可誤報。
拆到這裡,才輪到它能拿來幹嘛
機制清楚了,用途自己浮出來。
三個前置條件:Claude for Teams 或 Claude for Enterprise 方案、Owner 或 Primary Owner 角色(Admin 與其他非 Owner 角色看不到也改不了)、能連到 api.anthropic.com 的網路。進 Admin Settings > Claude Code > Managed settings(https://claude.ai/admin-settings/claude-code)。連結會導到別的 Admin Settings 頁面,就代表這個帳號沒有那個角色。
settings.json 裡所有設定都支援,除了限定走 OS 層政策下發的那幾個。hooks 可以、環境變數可以、allowManagedPermissionRulesOnly 這類 managed-only 設定也可以。權限封鎖大概長這樣:
1 | { |
全公司 hook 也在同一份 JSON 裡,官方範例是一個 PostToolUse,matcher 寫 Edit|Write,command 打到 /usr/local/bin/audit-edit.sh。存檔之後,client 會在下一次啟動或每小時輪詢週期收到更新。
驗收看 claude doctor 的「Managed settings (remote)」那一行(需 v2.1.248 或更新),四種結果:設定已載入、組織沒設定、fetch 失敗(含原因與「快取政策是否仍生效」)、Claude Code 跳過了 fetch(含原因),還在抓就顯示進行中。/permissions 看實際生效的權限規則;/status 在 fetch 失敗與某些 skip 原因(第三方供應商變數、shell 裡 export 的自訂 ANTHROPIC_BASE_URL)時顯示同一行。
要更細就 claude --debug-file <path> 然後搜 "Remote settings"。整包 payload 救不回來時,log 會寫 Remote settings: Settings validation failed - no fields could be salvaged。
推給全組織之前,先在測試機上跑一次 claude doctor。
限制有三條。設定一律套用到組織裡所有使用者,還不支援分群。不能用它發 managed-mcp.json 檔,要改用 allowedMcpServers 與 deniedMcpServers 政策鍵(v2.1.259 或更新版可以用 managedMcpServers 提供遠端 server,但只吃 http 與 sse,也不像那個檔取得排他控制權)。限定 OS 層政策來源的設定不被採納,文件點名 policyHelper 與 wslInheritsWindowsSettings,得走 MDM 或系統 managed-settings.json。
那條 deny 規則沒有你想的那麼硬
文件自己在上面那個權限範例底下附了警告,值得抄過來。Bash(curl *) 比對的是 Claude 寫出來的那個字面指令,它比對不到 /usr/bin/curl,也比對不到 sh -c 'curl …'。要做不依賴指令文字的網路管制,得改加 sandbox 區塊配 allowManagedDomainsOnly。
這個形狀在權限規則的五種漏擋形態那篇拆過,不重述,要記的只有一句:換了下發通道,規則本身的脆弱程度一點都沒變,你只是讓同一條脆弱的規則出現在更多台機器上。
更難的一條:使用者可以把你的 fetch 整條拆掉
文件的定性很直白:
they operate as a client-side control, not a security boundary. On unmanaged devices, a user doesn’t need admin or sudo access to bypass them.
繞過的方式文件列了八種,最值得知道兩條。
第一條是改快取檔。~/.claude/remote-settings.json 被竄改之後,改過的內容會在啟動時套用(withheld 那批除外)。下次 fetch 會修正回來,但那些只在下次啟動才套用的鍵(model、新加進 env 的變數)會一直錯到重啟為止。
第二條最該記住。使用者只要設一個第三方模型供應商,整件事就直接繞過去。文件點名 CLAUDE_CODE_USE_BEDROCK、CLAUDE_CODE_USE_MANTLE、CLAUDE_CODE_USE_VERTEX、CLAUDE_CODE_USE_FOUNDRY、CLAUDE_CODE_USE_ANTHROPIC_AWS,或一個非預設的 ANTHROPIC_BASE_URL。
麻煩在於你補不回來。
想用 server-managed 的 env 區塊去清掉那個 export?那個區塊正是走「被這個 export 擋掉的 fetch」送來的,根本到不了這台機器。改用 endpoint-managed 的 env 區塊?也救不回來,Claude Code 在套用 managed env 之前就先檢查資格了。
跟前面 withheld 那段是同一個形狀,攻守顛倒而已。原廠先把「能改變 fetch 去向」的值扣住,免得被自己下發的東西反咬一口;使用者那個 export 動的是同一個把手,只是它在 fetch 發生之前就已經存在,所以扣不住。
文件給的兩條解法都不在 server-managed 這一層:把 export 從 shell 移掉,或者在使用者的 user settings env 區塊把該變數設成 ""(這個會在資格檢查之前生效)。兩條都要有人碰到那台機器。
繞回最前面那台沒裝 MDM 的筆電。它確實能被管到,前提是使用者沒有主動反抗。我的立場是,這東西買到的是一致性,不是強制力。拿來鋪預設值、鋪稽核 hook、鋪「大家都該有但沒人想自己設」的那些東西,它很好用,而且是目前唯一能覆蓋雲端 session 的路:endpoint-managed settings 到不了 Anthropic 託管環境,session 跑在 Anthropic 管的 VM 上,所以就算有 MDM,只要開發者會用 cloud session,你還是得再配一份。拿它當唯一那道防線,就是把稽核報表當成事實。
會讓我改口的條件很具體:哪天資格檢查搬到套用 managed env 之後,或者未帶政策的 client 在伺服器端就直接被拒絕發模型請求,上面那段就不成立了。
想讓它硬一點:fail-closed 那個開關
預設是 fail-open,fetch 失敗就吃快取。要反過來,加這個鍵:
1 | { "forceRemoteSettingsRefresh": true } |
設了之後,CLI 啟動時會擋住,直到成功抓到新政策;抓不到就退出,不會不帶政策繼續跑。
這個鍵會自我延續。一旦從伺服器下發過,它自己也進了本機快取,所以之後每次啟動,即使在首次成功 fetch 之前,都是這個行為。
好在有一個豁免:claude auth 系列子指令(例如 claude auth login)不受這項檢查管。憑證過期常常就是 fetch 失敗的原因,連登入都被擋住的話,使用者會卡死在沒有出口的迴圈裡。
打開這個鍵之前,先確認網路政策允許連到 api.anthropic.com,否則 CLI 會在啟動時退出,使用者完全開不起來。
這篇我只讀了文件,沒有實際跑過。 我手上沒有 Enterprise 方案的 Owner 權限,也沒有能拿來實驗的組織帳號,上面每個版本號、每個鍵名、每條行為都是文件明寫的。文件沒講清楚的地方我就留著,例如那個「每小時輪詢」有沒有可調的參數,我不知道。
這個形狀到處都是
抽掉 Claude Code 這個殼,剩下的長這樣:一條用來下發控制的通道,而通道的走向由被下發的內容決定。
DNS server 位址由 DHCP 下發,DHCP 要不要被信任又看網路怎麼接。設定管理工具管全機器的設定,包括它自己那個 agent 的設定。VPN 的路由規則從 VPN 裡面推下來。同一個洞:有人在通道建立之前就動了那個把手,你後面推的東西全部到不了。
判準也就清楚了。拿到任何一套遠端下發的控制,先攤開兩張清單:這條通道自己依賴哪些值,這套機制又能下發哪些值。交集就是你補不回來的部分。原廠會自己扣住一部分,withheld 清單就是為此存在;剩下的要嘛靠實體接觸那台機器,要嘛把控制點往伺服器端搬。
那張交集清單,多數系統的文件不會幫你列。這份列了。






































































































































































































