SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-13

編碼代理程式遙測會傳送哪些資料?

編碼代理程式會產生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_BUNDLESSL_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

每次更新後應檢查的項目

  1. 將供應商的設定與資料使用頁面,和上次記錄的內容逐項比對,確認是否新增開關或具名服務。
  2. /proc/<pid>/environ 重新讀取程序環境,確認停用選項仍套用至執行中的程序。
  3. 再次列印專案設定檔,因為 git pull 可能會載入同事修改過的設定檔。
  4. 執行完整一個實際工作階段的 SNI 封包擷取,並將主機名稱清單與上次的清單比對。
  5. 檢查防火牆的丟棄計數器,因為新的目的地通常會先出現在這裡,之後才會在其他地方察覺。

這大約需要十分鐘,而且這是流程中唯一不會過時的部分。你在 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_PROXYHTTPS_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。

#telemetry#privacy#coding-agents#secrets#auditing