四十八個德瑞克

程式碼 agent 把你的秘密抄進一個隱藏檔案,GitHub 上有數千個

AI 程式碼 agent 把金鑰帶出筆電、飄進雲端的抽象插畫

本文譯自 Apiiro 研究文章《Coding Agents Copy Your Secrets to a Hidden File. Thousands Are on GitHub》,作者 Shmulik Cohen、Matan Giladi,2026年11月5日發布。Apiiro 是應用程式安全公司,主產品做程式碼風險分析。

更新,11月8日:Anthropic 的 Claude Code 負責人回應了。 Boris Cherny(波里斯·切爾尼,Anthropic Claude Code 負責人)於11月7日在 Hacker News 回應,並在週末持續參與討論。他表示團隊「正在研究我們能做什麼來防止這種事」,列出打算原型驗證的方向,包括「確保 auto mode 能擋下這種情況、內建基本的秘密掃描」;當有讀者指出 auto mode 在詢問敏感指令時同樣會發生,他回答「抓得好」。完整回應見文末。

Apiiro 研究發現:1,994 個公開 GitHub repository 藏有2,539 組真實憑證——資料庫密碼、雲端金鑰、API token、SSH root 登入。其中包括某資料庫廠商自己的管理權限雲端金鑰、生產環境 Azure Postgres 密碼、Square 生產 token,以及一份醫療紀錄資料庫的 owner 密碼。多數屬於個人開發者。受影響的組織有63 個,從學生社團、新創公司、軟體外包商到老牌供應商都有。其中一家確認它的金鑰確實還在生效。

叫 Claude Code 檢查資料庫或呼叫 API,它提出的指令,會直接帶著你設定檔裡的祕密。執行前它會問你。選「是,而且不要再問」,它就把那條完整指令(含祕密)存進專案資料夾的 .claude/settings.local.json。repo 裡沒有任何東西標記這個檔案是私密的,於是它就跟著其他程式碼一起被 commit 上網。

GitHub 上這個檔案有104,185 份公開副本,其中1,122 份含有真實憑證。研究另外在 git history、團隊刻意共用的 settings.json、以及存在 repo 裡的 agent 對話紀錄中,又找到1,160 組。

先自我檢查

公開了嗎? 在你的 GitHub 組織裡搜尋 .claude/settings.local.json 與 .claude/settings.json。每一個命中都是一個現在就能被任何人讀取的檔案。

曾經被 commit 過嗎? 檢查每個 repo 的 git history 有沒有這個檔案,即使今天已經不在了。只要 history 有,每個 fork 和 clone 都有。

裡面是什麼? 找出機器上每一份這個檔案,讀它的白名單。每一條都是你核准過的指令,連同你當時打進去的內容:找密碼、token、金鑰、連線字串。

找到了: 先輪換(rotate)憑證,再清理。

秘密怎麼進到設定檔裡

開發者機器上到處是秘密:設定檔裡的資料庫連線字串、本機安裝的雲端金鑰、.env 裡的 API token。叫 Claude Code 查 staging 為什麼登入失敗、或執行資料庫遷移,它提出的指令會帶著這個秘密,因為沒有它指令跑不動。Claude Code 每次執行 shell 指令前都會問,一場工作下來問個沒完。被打斷第十次之後,多數人就不讀指令了,而秘密只是長長一行裡的一個詞。

選「是,而且不要再問」,它就執行指令,並把一條權限規則加進專案資料夾的 .claude/settings.local.json,以後不再問。而規則的內容就是那條指令字串本身。

這是 Claude Code 本身的行為,不是模型的:用 Anthropic 最新模型也會發生,研究用 Opus 5.5 與 Fable 5.1 都重現了。

這個檔案本來就該留在開發者機器上,Claude Code 也試著這樣做。當它在 git repo 裡建立這個檔案時,會把它加進開發者的全域 git ignore 清單。這涵蓋了常見情況,但涵蓋不了「資料夾之後才變成 repo」「在另一台機器上 clone」「檔案早就被 commit 過」。這條規則永遠不會進 repo 自己的 .gitignore,所以沒有東西會跟著專案一起走、替它提供保護。

Claude Code 其實知道檔案已被 git 追蹤:權限文件寫說被追蹤的副本視為 repository 提供,它的 debug log 也會記錄「is tracked in the index; gitignore rules do not apply to tracked files」。但使用者不會被通知,下一次核准還是照樣追加進那個被追蹤的檔案。

而且常常是 Claude 自己把檔案 commit 進去的。在追查的1,105 個含真實憑證的 repo 中,有539 個的某次 commit 由 Claude 共同署名並修改了這個檔案。那些 commit 提到所有近期模型,從 Sonnet 4.5 到 Opus 5.5。Claude Code 的 commit 指示會告訴模型不要 commit .env 或 credentials.json——但它自己的設定檔不在那份清單上。

誰暴露了

63 個組織的公開白名單裡含有真實憑證。最嚴重的幾個案例都在 .claude/settings.local.json,每一筆都以固定 commit 檢查過:

組織 暴露了什麼
資料庫廠商 自己的雲端 API 金鑰(manage 權限、宣稱無到期日)+叢集主機
B2B 新創 生產環境 Azure Postgres 密碼
軟體外包商 Square 生產存取 token
開源專案(超過1,000顆 star) OpenAI 格式的 API 金鑰
開源專案 npm token
IT 服務商(醫療紀錄 app) 該 app 雲端 Postgres 資料庫的 owner 密碼
支付新創 postgres 角色的 Postgres 密碼

這些組織從學生與駭馬松社群,到新創、軟體外包商、IT 服務公司都有;少數是老牌供應商,透過自己的 demo 與工作坊 repo 暴露。沒有任何人想公開金鑰——金鑰在指令裡、指令被核准、檔案就跟著其他東西一起被 commit 了。

白名單裡還有伺服器登入憑證:43 組公開伺服器的 SSH 憑證,其中有些是 sshpass 指令裡的 root 密碼。例如某大學有個 repo,永久核准了對公開伺服器的 root SSH 指令。

有多少

公開 GitHub 上有104,185 份 .claude/settings.local.json,分布在103,617 個 repo。其中1,122 份(1.1%)含有真實憑證:符合已知供應商格式的金鑰,或與公開主機並列的密碼、token。這些檔案合計含1,379 組不同憑證:636 組供應商金鑰、743 組公開主機的密碼或 token。

超過三分之一是直接開資料庫用的:379 組資料庫密碼、122 組 Supabase service-role 金鑰。另有103 組 Supabase 帳號 token,能控制該帳號下每個專案。其餘大多是第三方服務的 API token 與 AI 模型金鑰,加上43 組 SSH 登入、42 組 GitHub、GitLab、npm token、23 組 AWS 金鑰、6 組私鑰。

白名單越大越危險:超過8 KB 的檔案中每十份就有一份含真實憑證,500 位元組以下的檔案不到五百分之一。開發者按「不要再問」按得越久,檔案就塞得越滿。

檔案還在那裡:2026年11月2日,每一份都還躺在所屬 repo 的預設分支上,而且多數已經躺了很久。含真實憑證的 repo 中,該檔案首次進版控的時間,中位數落在 217 天之前;118 個 repo 更早一年多就進去了。

Fork 會把它們複製走:這74 個 repo 的211 個 fork,都帶著同樣的憑證。

刪掉檔案也沒用:舊版內容裡還有734 組真實憑證,分布在509 個 repo,且不出現在任何現存副本中——通常就是因為檔案被刪了。

把檔案歷史、共用設定檔與 agent 對話紀錄一起算進去,總計1,994 個 repo 裡有2,539 組不同真實憑證。

秘密掃描器漏掉了什麼

通用秘密掃描器漏掉很多這類東西。研究對全部104,185 份檔案跑了 gitleaks 與 TruffleHog。在1,122 份含真實憑證的檔案中,gitleaks 標記564 份、TruffleHog 標記643 份,兩者都沒標記的有215 份。

漏洞在「指令裡的密碼」。掃描器找的是金鑰格式:供應商前綴、一長串亂數。打在 PGPASSWORD=、sshpass -p 或 mysql -p 後面的密碼,或是 curl 裡的 bearer header,在掃描器眼裡就是普通指令列上的普通單字,兩個工具大多放行。

這不只影響這個檔案。同樣的「指令裡藏密碼」模式,出現在 agent 記錄自己執行過什麼的每一個地方:對話紀錄、記憶體檔案、交接筆記,而只針對金鑰格式調校的掃描器在這些地方全都漏。

不只一個檔案

白名單是最明顯的案例,但 agent 還會把秘密寫進開發者會 commit 的其他檔案。

檔案 檢查數 含真實憑證
共用 .claude/settings.json 全部76,011 298 份
agent 對話紀錄(.specstory、aider、Cursor 匯出) 2,523 87 個 repo 中120 份
agent 記憶體檔案(MEMORY.md 等) 1,200 9 個 repo
交接與部署筆記 2,095 33 份
VS Code Copilot 自動核准設定 173 9 個 repo

共用設定檔是團隊刻意 commit 的,其中多數秘密以完整指令列的形式躺在允許規則裡。有秘密的交接筆記中,三分之一是 agent 自己寫的。

檔案也會離開 GitHub:31,053 個 Hugging Face Spaces 中有126 個帶有 .claude/settings.local.json,其中一份的允許規則含資料庫 service 金鑰與使用者密碼。GitLab.com 上抽查的69 份公開副本有2 份含真實憑證,包含一組 GitLab access token。

到處漏的都是同一個習慣:把秘密打進指令,再讓 agent 把指令記下來。

開發者機器上

大多數這些檔案從沒上 GitHub,留在開發者機器上——那也不安全。白名單就是專案資料夾裡的純文字 JSON。

惡意軟體早就會批次蒐集開發者機器上的憑證。2025年9月的 Shai-Hulud npm worm 下載了 TruffleHog,對受害者的檔案跑掃描——那套工具能標記這1,122 份檔案中的643 份。三週前,惡意的 Nx 套件,則指示開發者自己的 Claude Code 與 Gemini CLI 去磁碟上搜尋秘密。

檔案也可能不經 git 就離開:發布出去的 npm 套件、帶 copy 指令建出來的 Docker 映像、zip 壓縮檔或同步資料夾。而核准過一次的秘密會一直留在檔案裡,直到有人刪掉那條規則——早就過了指令實際執行的時間。

先前研究

本文新增的是:GitHub 全量的秘密外洩統計、組織案例、掃描器漏洞,以及攜帶同樣秘密的其他 agent 檔案。Claude Code 使用者從2025年8月起就在 GitHub issue 回報這個機制(#5544、#11982、#13106、#91270)。沒有任何一則得到 Anthropic 回應,其中三則被自動關閉,理由是不活躍或重複。ironPeak 在2026年2月也於自己的 repo,發現同樣的檔案,並在100 份抽樣中量到2.4% 的 repo 若歷史中帶有 AI 設定資料夾就含憑證。Lakera 在4月發現30 個 npm 套件中的33 份此類檔案含憑證。

該怎麼做

開發者:

  1. 檔案若已被 repo 追蹤,用 git rm --cached .claude/settings.local.json 取消追蹤,並加進 repo 自己的 .gitignore。
  2. 輪換這個檔案持有過的每一組憑證。刪掉它不會清掉 git history、fork 與 clone。
  3. 即使檔案從未被 commit,也開啟它、刪掉每一條含秘密的規則。
  4. 別再把秘密打進指令。用你秘密管理工具的 $VAR 引用,讓規則記錄的是 $DB_URL 而不是秘密本身。
  5. 核准模式(如 Bash(npm run:*)),不要核准字面指令。

資安團隊:

  1. 把 agent 資料夾(.claude/、.cursor/、.gemini/、.specstory/、agent 記憶體檔案)視為攜帶秘密的東西,就像 .env 一樣——筆電上與 repo 裡都一樣。
  2. 把它們加進 pre-commit 與 CI 的秘密掃描,含歷史。確認掃描器抓得到「指令裡的密碼」(PGPASSWORD=、sshpass -p、mysql -p、bearer header),不只抓供應商金鑰格式。
  3. 把 .claude/settings.local.json 加進組織的 .gitignore 範本。
  4. 優先處理「憑證+公開主機」組合——那些才是真正給出存取權的。

Anthropic 的 Claude Code 負責人回應

研究在發布前把資料分享給 Anthropic。上線後,Boris Cherny(波里斯·切爾尼,Anthropic 的 Claude Code 負責人)於11月7日在 Hacker News 回應,週末期間共發了十則留言。

從歷史上看 Claude Code 沒有做秘密清除(secret scrubbing)——那方面有很多好工具——但我們正在研究能做什麼來防止這種事。

關於做法:

有幾個可能方向:確保 auto mode 能擋下這種情況、內建基本的秘密掃描,還有其他幾個想法。我們會先原型驗證其中幾個、搞清楚取捨,再推出什麼。

當有讀者指出 auto mode 在詢問敏感指令時同樣會發生:

嗯,抓得好。正在想我們能怎麼改善(歡迎提想法)。

他也說 Claude Code 在建立檔案時會把它 gitignore,他認為這些外洩的副本,是使用者手動建立之後才提交進版控的;他建議用 auto mode 取代 permission rules;並建議開啟 GitHub 等平台提供的秘密掃描。

披露

研究方在2026年11月2日與3日把每個組織案例通報給其負責人,也透過 Anthropic 要求的披露管道及其他數個管道通知了 Anthropic。

方法與限制

蒐集。 全部資料來自2026年11月1日至3日對 GitHub 預設分支的唯讀程式碼與 commit 搜尋。程式碼搜尋每次查詢最多回1,000 筆,因此依檔案大小切分查詢,直到每片都在上限內。這列出103,617 個 repo 中的104,185 份 .claude/settings.local.json 與76,011 份共用 settings.json,而且每一份都下載了。檔案歷史涵蓋43,120 個 repo,包含每一個 commit 訊息提到移除、取消追蹤、遮蔽或輪換該檔的 repo,所以歷史計數是下限。Fork:每個含真實憑證 repo 的所有 fork。對話紀錄、記憶體檔案、交接筆記與 Copilot 設定透過搜尋金鑰前綴與連線字串找到。研究比較了16 個程式碼 agent 的文件,看它們如何儲存核准——Claude Code 是唯一確認預設會把完整核准指令寫進專案檔案的。

分類。 研究使用秘密掃描器的兩類偵測器。供應商格式比對已知金鑰格式:OpenAI、Anthropic、AWS、GitHub、npm、Supabase、Stripe、Slack 等。通用秘密是沒有已知格式的密碼與 token;只有當同行出現公開主機時才計入,例如連線字串,或 psql -h 前面的 PGPASSWORD=。規則再移除已知誤報:占位字串、常見預設密碼、本機與私有主機、設計上就公開的金鑰(Supabase anon key、Firebase web 設定)、本機 Supabase demo 金鑰、過期 token,以及內建驗證碼不符的 GitHub 與 npm token。剩下的每一個不同值共2,774 個,全部由獨立的 LLM 審核者依書面規範在其遮蔽語境中逐一審查。只有規則與審核一致才算真實憑證:全部來源合計2,539 組。記憶體檔案、交接筆記與 Copilot 設定只用規則分類。gitleaks 與 TruffleHog 的執行未經驗證。

限制。 沒有使用或測試任何憑證,也沒有連絡任何主機。「真實憑證」指符合供應商格式或指向公開主機的憑證,不代表已知有效。每個組織案例都在固定 commit 的連結上檢查過。

Hacker News 討論整理

原文在 Hacker News 引發大串討論(story 50407882,595 分、404 則留言,2026-11-09 11:49 抓取;留言總數含已刪,頂層58 個 slot 中可讀41 則)。以下整理自該串與站內日報底稿。

爭議核心不在漏洞本身,而在 Anthropic 的官方回應。 Claude Code 團隊的 Boris Cherny 親自下場,除了說明「該檔不該進版控」,還丟出一句「permission rules 是老東西了,大家應該改用 auto mode」,讓整個子串變成質疑現場。

安全不能用「模型自己判斷」取代靜態規則。 @syllogism:「我要在 agent 能做的事周圍劃下確定性的界線。我不接受用機率的方式做安全。」@adastra22 直接對 Boris 開火:「我不想信任機器。信任機器就是我們走到今天這一步的原因。我要的是精確、確定、永遠會被遵守的規則。」

「auto mode 更安全」在沒有沙盒的前提下是空話。 @OJFord:「在沒有搭配真正沙盒的情況下,這句話完全是瘋話。」@markasoftware 指出 auto mode 根本沒有定義威脅模型,無法與其他方案量化比較。

病灶是「把整串指令存進白名單」,不是按鈕。 @anatolii1309:「核准過一次帶 token 的 curl,那個 token 就會一直躺在 settings.local.json 裡。兩條有用的規則:密碼只透過環境變數進指令;.claude/ 放進機器全域 gitignore。」@binarymax 的做法是 1Password 加 op CLI,每次取用按指紋。

真正的解法是讓 agent 拿不到秘密。 @kstenerud 主張容器或 VM 完全隔離;@tsergiu 每個任務一台隔離網路上的臨時 VM,外面再套一層限制外部服務權限的 API proxy;@tomrod 的版本是 harness 在工具層做秘密注入,agent 只看得到工具清單。

官方態度被批推責任。 @doginasuit:「幾乎任何不是自己叫 Claude 建立專案的人,都可能洩漏密碼,已經有1,122 個具名受害者。任何想爭取信任的公司,都該明確承擔這個錯誤。」另一邊 @agentdev001 肯定回應速度快,並認為 harness 端做確定性防護某種程度上會讓工具變鈍。

也有網友校正標題黨式的理解。 @Aurornis 指出按按鈕本身不會洩密,是要把 local settings 提交進 repo、而且指令裡本來就手打了密碼才會洩;作者 @shmulc 回應補充:檔案建在專案裡,Claude Code 只加進使用者的全域 git ignore,不進 repo 的 .gitignore,所以新 clone 或第二台機器會把它當一般檔案提交。

視覺懶人包

開新視窗看完整版

Exit mobile version