編碼代理程式遙測會傳送哪些資料?
編碼代理程式會產生4類流量,只有模型推論無法停用。本文教你從本機稽核實際連線,找出分析、當機回報與整合功能的未同意傳輸。
編碼代理程式遙測實際涵蓋的內容
編碼代理程式遙測包含4種不同的資料分享流程,只是共用同一個名稱,而且每種流程都有自己的控制方式。模型推論會將您的提示與程式碼傳送給提供模型服務的一方,沒有任何設定可以停用這項傳送。產品分析資料與當機報告會傳送給廠商,且通常也會傳送給廠商付費使用的日誌服務公司。資料保留是否可用於訓練,屬於合約問題,而不是網路問題。人們最容易忽略的是第4種流程:您加入的每個整合,都可能對您從未選擇的主機建立連線。
目前廠商預設值清單是這個主題中變動最快、最容易失效的部分。版本發布可能變更預設值,新功能也可能加入現有開關未涵蓋的目的地。因此,能長期適用的做法,是針對任何代理程式重複執行稽核:閱讀廠商文件、確認這台機器實際套用的設定、從機器本身監看程序,然後選擇您願意付出成本採用的控制措施。以下每個指令都會在您自己的機器上,針對您自己的網路流量執行。
四種類別及其需要不同控制措施的原因
模型推論流量無法避免。 代理程式會將你的提示、讀取的檔案、執行指令的輸出,以及自行產生的文字傳送至模型端點。這就是產品的運作方式。唯一真正需要決定的是由誰接收這些資料:由他人執行的 API,或由你自行執行的模型。使用公司雲端帳戶(Bedrock、Vertex、Foundry)只會改變接收者,不會消除資料流。本文其餘內容都無法降低推論流量,因此請在概念上將它與其他三類流量分開。
產品分析與當機回報是傳送至不同主機的另一種資料流。 使用量計數器、延遲數值、功能旗標查詢及堆疊追蹤通常會傳送至與模型 API 無關的主機名稱,而且經常會傳送至第三方錯誤追蹤服務。供應商通常會將這些資料記載為「metrics」和「error reports」,並通常為每個類別提供一個環境變數。這類流量的總量很小,因此位元組計數永遠找不到它。你要追查的是主機名稱,不是頻寬。
資料保留與訓練屬於政策,不是封包。 供應商是否保留你的提示、保留多久,以及是否使用這些提示訓練未來的模型,都會寫在適用於你方案的條款中。消費者方案與商業方案通常不同,而零保留安排通常需要另行簽署協議。你無法使用 tcpdump 驗證這些事項,因為無論情況為何,封包看起來都相同。請閱讀條款;如果這對你的雇主很重要,請取得書面承諾。
整合功能會在背後增加一個轉送節點。 MCP(model context protocol)伺服器、外掛程式市集、自動更新檢查、網頁搜尋工具,以及在擷取 URL 前先解析該 URL 的安全性檢查,都會向模型端點以外的主機發出請求。意外通常發生在這裡,因為 harness 可能會將你以為在本機執行的工作,經由其自身的服務轉送出去;而版本發布後也可能開始這樣做,卻不必變更設定檔中的任何一行。除非你已在網路線路上觀察過,否則請將新增的每個工具都視為新的目的地。
步驟 1:查看廠商文件
開啟代理程式的設定參考文件與資料使用頁面,並準備一份詞彙清單逐項閱讀:metrics、analytics、error reporting、crash、feedback、survey、update check、safety check、marketplace。這些詞通常各自對應不同的開關。記下確切的變數名稱,因為步驟 2 會使用 grep 搜尋這些名稱。
其中有一個詞容易造成誤解。在多個代理程式中,文件裡的「telemetry」是指 OpenTelemetry 匯出功能,也就是設定代理程式將 metrics 傳送到由你執行的 collector;這與將資料傳送給廠商的情況相反。Claude Code 就是其中之一:設定 CLAUDE_CODE_ENABLE_TELEMETRY=1 會啟動匯出功能,並將資料傳送到你在 OTEL_EXPORTER_OTLP_ENDPOINT 中指定的 endpoint。這與廠商自己的 analytics 無關,後者有不同的退出設定。設定任何項目前,先確認資料的流向。
預期會有一個主要開關,但也要注意它可能涵蓋不完整。截至 2026 年 8 月,Claude Code 的 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC 會一併關閉 metrics、error reports、feedback command 與 session surveys;同一份文件也指出,它不涵蓋 WebFetch domain safety check。該檢查會將即將擷取的 hostname 傳送至廠商 API,並有獨立的設定。這不是單一產品的問題,而是普遍存在的情況:主要開關只涵蓋撰寫文件時已存在的類別。
也要預期退出功能可能會帶來代價。同一份文件指出,停用 telemetry 也會停用部分功能所依賴的 feature-flag evaluation。因此,為了隱私而關閉某個開關,可能同時停用你正在使用的功能,而且不會顯示能將兩者關聯起來的錯誤訊息。不要只看 flag 名稱,也要閱讀它旁邊的說明。
第2步:實際套用的是哪份設定?
你寫入的設定,不代表實際套用的設定。代理程式會合併多個檔案中的設定,其中一份可能位於你剛從他人處複製的儲存庫內。先從你自己的 shell 環境開始檢查。
env | grep -Ei 'telemetry|otel|analytics|error_report|do_not_track|proxy'接著依照文件列出的順序,列出工具讀取的每一份設定檔。以 Claude Code 為例,截至 August 2026,這包括使用者檔案、2 份專案檔案,以及 Linux 上的受管理原則目錄。
for f in ~/.claude/settings.json .claude/settings.json .claude/settings.local.json; do
echo "== $f"; [ -f "$f" ] && cat "$f"
done
ls -l /etc/claude-code/ 2>/dev/null隨 git clone 一同加入的專案檔案,代表設定可能是陌生人寫入的,而且可以重新啟用你在使用者檔案中停用的功能。如果代理程式提供列出已載入來源的 status command,這是最快取得實際結果的方法:Claude Code 會在 /status 列出已載入的設定來源。
最可靠的檢查方式,是直接讀取執行中的 process,而不是讀取任何檔案。先為代理程式建立專用的 Linux user account,讓本文中的每個 command 都更精簡,再讀取該 process 啟動時取得的環境。
pgrep -u agent -a node
sudo tr '\0' '\n' < /proc/$(pgrep -u agent -n node)/environ | grep -Ei 'telemetry|proxy|otel'/proc/<pid>/environ 顯示 process 在 exec 時取得的變數,因此可以找出 .bashrc export 未傳遞給 systemd 啟動的 service 的情況。如果你設定的變數未出現在這裡,代表它從未生效,不論 dotfiles 中寫了什麼。
步驟 3:它會連線到哪些主機?
先查看開啟的 socket,並依 agent 執行時使用的帳號篩選。
sudo ss -tnpe state established-e 會在每一行加入 uid: 欄位,因此不必查看程序名稱,就能將 agent 的連線與瀏覽器的連線分開。記下遠端位址,再查出這些位址背後的名稱。最可靠的名稱來源是 TLS(transport layer security)交握,因為每個新連線都會先傳送包含 SNI(server name indication)欄位的 ClientHello。該欄位就是用戶端要求連線的主機名稱。
sudo apt install -y tshark
sudo tshark -i any -f 'tcp port 443' -Y 'tls.handshake.type == 1' \
-T fields -e ip.dst -e tls.handshake.extensions_server_name每個新連線各佔一行,這正是所需的清單:模型 API、更新伺服器、分析主機、錯誤追蹤服務,以及整合功能新增的任何連線。名稱欄為空,表示用戶端使用了 ECH(encrypted client hello),因此線路上看不到主機名稱。此時改用目的地 IP 位址、反向查詢,或步驟 4 的代理伺服器。
DNS(domain name system)檢視可用來交叉核對,因為即使 agent 未完成連線,也能顯示它查詢過的名稱。
sudo tcpdump -ni any -l 'udp port 53'每一行查詢最後都會以 A? host.example.net. (39) 的形式顯示記錄類型與名稱。在 any 上進行擷取,不要在外部介面上擷取,因為使用 systemd-resolved 時,應用程式會與 127.0.0.53 上的本機 stub listener 通訊,只有該 stub 會對外通訊。如果 agent 明確正在運作,但完全看不到 DNS 流量,表示該執行環境自行使用 DNS over HTTPS;只有步驟 4 能提供名稱。
請在 agent 執行實際工作時進行擷取。啟動工作階段,讓它讀取檔案、執行命令,並讓它在某個操作中失敗。啟動時只發生一次,或僅在擲回例外時產生的流量,不會出現在閒置擷取中。閒置擷取是稽核得出看似合理但實際錯誤結論的最常見原因。
步驟 4:請求中有什麼內容?
主機名稱能告訴你請求的對象。若要查看請求內容,請在 agent 前方放置由你控制的 proxy,並僅針對該 runtime 信任其憑證授權單位(CA)。通常使用 mitmproxy。該專案建議使用 mitmproxy.org 提供的獨立二進位檔,並在 uv tool install mitmproxy 中說明 Python package 的安裝方式。
mitmdump -w /tmp/agent-flows.mitm第一次執行時,系統會將 CA 寫入 ~/.mitmproxy/,其中 mitmproxy-ca-cert.pem 是單獨的憑證檔案。在啟動 agent 的 shell 中,將 client 指向 proxy 與該憑證。
export HTTP_PROXY=http://127.0.0.1:8080
export HTTPS_PROXY=http://127.0.0.1:8080
export NODE_EXTRA_CA_CERTS="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"
export REQUESTS_CA_BUNDLE="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"
export SSL_CERT_FILE="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"許多 agent CLI 都是 Node 程式,而 Node 會在程序啟動時讀取 NODE_EXTRA_CA_CERTS,因此請在啟動 agent 前匯出此變數,不要在另一個終端機中事後設定。Python client 會讀取 REQUESTS_CA_BUNDLE 或 SSL_CERT_FILE;在 Linux 上使用標準函式庫的 Go binary 則會讀取 SSL_CERT_FILE。在將問題歸咎於 agent 前,先使用 curl 驗證該路徑可正常運作。
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com正常運作的 proxy 會輸出 200,而請求會出現在 mitmdump 的輸出中。不受信任的 CA 會產生 curl: (60) SSL certificate problem: self-signed certificate in certificate chain;Node agent 對應的錯誤則會帶有 SELF_SIGNED_CERT_IN_CHAIN 代碼。之後使用 console viewer 讀取已儲存的 flows;你可以開啟單一請求,查看其標頭與本文。
mitmproxy -r /tmp/agent-flows.mitm有 4 種結果值得區分。第一種是看得到請求,此時請讀取內容並自行判斷。第二種是 agent 因憑證錯誤而拒絕啟動,這表示該 runtime 存在信任問題,不代表已發現 vendor 的問題。第三種是只能看到 model API,表示其他類別未啟用,或只有在你未觸發的事件發生時才會執行。第四種是 agent 明顯正常運作,但完全看不到任何內容;這表示 client 忽略 proxy 環境變數,或釘選了憑證,因此不能依賴應用程式設定來判斷實際情況。最後一種結果最重要,也會讓你回到步驟 3,因為 packet capture 會如實顯示連線,無法透過說服它而改變結果。
控制措施:從最弱到最強
退出設定。 成本最低,強度也最弱,因為這類設定仰賴供應商遵守,也只能涵蓋原本已存在的類別。請在重新開機及開啟新終端機後仍會保留的位置設定,例如使用者設定檔或 shell profile。也請一併加入 DO_NOT_TRACK=1:許多 command line 工具都遵循這項慣例,部分 agent 也支援,而且不增加成本。下一次更新後重新執行步驟 3,因為此時涵蓋範圍會改變。
輸出流量限制。 這會讓你停止請求,開始強制執行。讓 agent 以專用使用者身分執行,然後只允許該使用者存取 loopback 與 DNS,丟棄其餘流量。這會建立自己的 table,因此不會影響現有的防火牆規則。
table inet agentegress {
chain output {
type filter hook output priority filter; policy accept;
meta skuid "agent" ip daddr 127.0.0.0/8 accept
meta skuid "agent" udp dport 53 accept
meta skuid "agent" counter log prefix "agent-egress-drop " drop
}
}使用 sudo nft -f /etc/nftables.d/agent.nft 套用設定,使用 sudo nft list table inet agentegress 監看計數器,並使用 sudo journalctl -k -g agent-egress-drop 讀取丟棄的流量。丟棄計數器持續增加,且對應到你未預期的主機名稱,正是這項操作要找出的結果。有兩項實際限制。meta skuid 比對擁有 socket 的使用者,因此只有在該帳號無法切換成其他使用者時才有效:若 agent 可免密碼執行 sudo,這項規則就只剩建議性質。若允許連往任意 DNS server 的 UDP 53,查詢名稱仍可成為資料外傳通道;如果你的威脅模型要求封鎖這項通道,也應一併關閉,方法是將 agent 的 resolver 指向你管理的主機。主機名稱 allowlist 應放在 proxy,而不是 nftables,因為 API endpoint 位於 content delivery network 後方,其 IP 位址會在你無法控制的情況下變更。這項控制措施的代價是服務中斷與維護負擔:package 安裝、透過 SSH 執行的 git,以及 agent 自身的更新檢查,都會在你允許它們之前失敗,而這份允許清單將由你負責維護。如果你是在 server 而不是 laptop 上設定,在 VPS 上安全執行 Claude Code 所採用的相同帳號與防火牆配置,就是基本架構。
一次性機器。 為 agent 提供一台不含重要憑證的 virtual machine (VM),並在工作結束時銷毀。這不會減少 agent 傳送的內容,而是減少 agent 能夠存取並傳送的內容;通常後者才是你真正需要控制的風險。請搭配上述輸出流量規則,因為即使是全新的 VM,只要能不受限制地存取 internet,仍可連到 capture 中的每台主機。相關方法,以及每次都必須重建的狀態,請參閱在一次性 VM 中執行 coding agent;規模配置問題請參閱在 VPS 上執行 coding agent。
自行託管 model。 這是唯一能移除 inference 流程的控制措施,因為 prompt 從未離開你的硬體。代價很高:你無法自行託管 closed model,因此必須選擇 open weights,接受其在困難工作上的能力差距,並準備用來提供服務的硬體。相關取捨請參閱你是否能自行託管 Claude;主要 agent 之間的能力差異請參閱Claude Code、Cursor、Codex 與 Copilot 的差異。
這四項控制措施都不會改變 agent 允許讀取磁碟上哪些內容,而 inference 流量會攜帶它讀取的所有內容。如果工作目錄中有 .env 檔案,agent 一旦 grep 某個變數名稱,該檔案就會傳送給 model。讓這些資料無法被 agent 存取是另一項工作,相關內容請參閱避免 secret 進入 AI agent 的 context。
每次更新後應檢查的項目
- 將供應商的設定與資料使用頁面,和上次記錄的內容逐項比對,確認是否新增開關或具名服務。
- 從
/proc/<pid>/environ重新讀取程序環境,確認停用選項仍套用至執行中的程序。 - 再次列印專案設定檔,因為
git pull可能會載入同事修改過的設定檔。 - 執行完整一個實際工作階段的 SNI 封包擷取,並將主機名稱清單與上次的清單比對。
- 檢查防火牆的丟棄計數器,因為新的目的地通常會先出現在這裡,之後才會在其他地方察覺。
這大約需要十分鐘,而且這是流程中唯一不會過時的部分。你在 August 2026 驗證的預設值,只能代表 August 2026 的狀態。封包擷取結果才代表今天的狀態。
FAQ
我可以阻止 coding agent 將我的程式碼傳送給 model 嗎?
不行。任何聲稱可以的設定,實際描述的都是其他功能。將你的提示、agent 讀取的檔案,以及它執行之命令的輸出傳送至 model endpoint,是推論的運作方式。因此,唯一可變的是接收者。你可以將 agent 指向公司的 cloud account,或指向自行代管的 model,以變更接收者;也可以限制 agent 可讀取的內容,以減少傳送的資料。關閉 analytics 和 error reporting 完全不會影響這個流程。
如何查看 coding agent 連線到哪些主機?
讓 agent 以獨立的 Linux user 執行,然後在使用期間擷取每個新連線的 TLS ClientHello:sudo tshark -i any -f 'tcp port 443' -Y 'tls.handshake.type == 1' -T fields -e ip.dst -e tls.handshake.extensions_server_name。每個連線會顯示一行,包含目的位址與要求的 hostname。使用 sudo tcpdump -ni any 'udp port 53' 交叉核對名稱,並在 any 上進行擷取,因為 127.0.0.53 上的 local resolver stub 會先處理查詢。請在 agent 實際執行工作時進行擷取,因為啟動 ping 和 crash report 不會出現在閒置擷取中。
agent 執行時,我的 proxy 沒有顯示任何 network traffic。哪裡出錯了?
可能是 client 忽略 HTTP_PROXY 和 HTTPS_PROXY,也可能是 client 固定使用憑證,因而拒絕你的 CA。先使用 curl 測試路徑:如果 curl 能透過 proxy 連上網際網路,但 agent 沒有出現在 flow list 中,表示 agent 沒有使用 proxy environment variables。有些 runtime 需要以特定方式提供 CA;Node 尤其只會在 process 啟動時讀取 NODE_EXTRA_CA_CERTS,因此在啟動 agent 後再 export 不會生效。proxy 無法查看 network traffic 時,改用封包擷取,因為任何應用程式設定都無法繞過封包擷取。
關閉 telemetry 是否能阻止我的程式碼被用於訓練?
不能。analytics 和 crash reporting 與 inference 是不同的流程,因此停用它們只會移除使用量計數器與 stack trace,而傳送至 model 的每個提示仍完全相同。這些提示是否會被保留,以及是否會用於訓練未來的 model,取決於方案條款;consumer plan 和 commercial plan 通常有所不同。這是需要閱讀的合約問題,不是需要擷取的封包。因此,請查看方案的 data usage page;如有需要,請在第一次 session 前安排 commercial 或 zero-retention agreement。