以隱形墨水寫成
Socket 發現了 TrapDoor,一場橫跨 npm、PyPI 與 Crates.io 的供應鏈攻擊,做了前所未見的事:一個安裝的套件會改寫你程式代理自己的規則檔——CLAUDE.md、.cursorrules——並把指令藏在你看不見的零寬 Unicode 裡。下次你執行代理時,它會讀自己的內部規則,跑一個「安全掃描」,收集你的 SSH 金鑰、雲端憑證、GitHub token 與加密錢包。指令是隱形的;竊取是真的。Bromure Agentic Coding 遞給那個掃描一個沒有任何值得拿走之物的盒子。
一個你安裝的套件,會編輯你程式代理最信任的檔案——它自己的規則檔——並用 顯示為空無一物的字元寫下惡意的一行。你檢視檔案,看到尋常的專案筆記,於是 核准。代理讀同一個檔案,卻看到一道命令:跑一個安全掃描,把結果送到這裡。
我們報導的多數攻擊,都把惡意指令藏在代理會讀到的某處——一個網頁、一則 拉取請求留言、一份 README。這一次卻藏在你最不會想到去查看的地方:代理 自己的設定。2026 年 5 月 22 日,Socket 開始追蹤一場它命名為 TrapDoor 的攻擊——橫跨 npm、PyPI 與 Crates.io 發布的 34 個惡意套件與超過 384 個版本,操作者重新發布的速度比下架還快。 Socket 的自動化資訊流平均在五分五十六秒內捕捉到新版本;最快的一次,在 發布後五十八秒。The Hacker News 與 Phoenix Security 在同一週報導了此事。我們現在寫它,是因為它最新的一手,是迄今為止最乾淨的 一個範例——一個為了直接瞄準程式代理而打造的供應鏈竊賊。
這些套件看起來就像開發者不假思索就伸手去拿的工具:環境載入器、錢包檢查器、
建置輔助工具,以及——那個一切的開端——eth-security-auditor,一個
「安全稽核工具」。裝上一個,它就做尋常竊資者的事。但共用的 npm 酬載,一個
名為 trap-core.js 的 48 KB 檔案,還多做了一件毫不尋常的事。它會寫入
.cursorrules 與 CLAUDE.md。
你看不見的那一行
這兩個檔案是內部規則。Cursor 讀 .cursorrules;Claude Code 讀 CLAUDE.md。
它們存在,是為了讓儲存庫告訴代理在這個專案裡該如何行事——慣例、該做與
不該做的事——而代理把它們當成常設指令,套用到它在那個資料夾裡做的一切。
那是工作空間裡最受信任的文字,因為理應是你自己寫的。
TrapDoor 寫進它們,並把寫下的東西藏起來。惡意指令用零寬 Unicode 字元編碼——
U+200B、U+200C、U+200D、U+FEFF——這些碼位文字編輯器根本不會顯示。
打開 CLAUDE.md,你看到的是尋常的專案筆記。跑 git diff,依你的設定,你
或許看不到任何值得停下來的東西。位元組在那裡;字形不在。那是一則以隱形
墨水寫成的訊息,唯一能把它顯影的讀者是代理,它會解析整段 Unicode 串流,
在自己的規則書裡發現一道指令。
竊取的掃描
隱藏的指令要代理跑一個「安全掃描」。這聽起來沒什麼令人警惕——你交給代理一個
安全稽核工具,如今它的規則要它去稽核。掃描實際做的,是在機器上四處走動,
尋找任何值錢的東西。Socket 對酬載的拆解列出了 SSH 金鑰、AWS 憑證、GitHub
token、瀏覽器設定檔與登入資料庫、環境變數與 API 金鑰,以及——這場攻擊的
簽名——加密貨幣錢包:Sui、Solana、Aptos,以及瀏覽器的錢包擴充功能。然後它
外洩到一個 GitHub Pages 網站(ddjidd564[.]github[.]io),在 Crates.io
版本中則外洩到 GitHub Gists。
有個細節顯示這有多刻意。在送出任何東西之前,酬載會「主動呼叫 AWS 與 GitHub 的 API,確認被竊憑證是否有效,在外洩前篩選出高價值的 token」。它不只是抓了 就倒出去。它把每一份憑證拿去對真正的服務測試,留下活的,丟掉死的。操作者 要的是一份乾淨的、能用的金鑰清單。
Phoenix Security 點出這為何最狠地打中它所瞄準的人:加密與 DeFi 開發者, 因為「SSH 金鑰、雲端憑證、GitHub token 與加密錢包金鑰庫,慣常地共存在同一 台機器上」。那句話就是整個攻擊面。代理在你的筆電上、以你的身分執行,一切 值錢的東西都在它的觸及範圍內。規則檔裡那看不見的一行只是扳機;周遭的存取 權才是酬載。
Bromure 在哪裡劃線
Bromure Agentic Coding 不倚賴揪出那看不見的一行——雖然,稍後會談到,它會讀 同樣的位元組。它改變的是,那一行觸發時能觸及什麼。每個設定檔的代理都跑在 Apple Silicon 上一個用完即棄的 Linux VM 裡,與 macOS 隔著一層 Hypervisor, 而那個盒子裡的憑證不是你的。
憑證是誘餌。 這是 TrapDoor 一頭撞進去的那一層,因為 TrapDoor 骨子裡就是
一個憑證竊賊。主機上的一個憑證仲介,
把你真正的 Anthropic、AWS 與 GitHub 祕密完全擋在盒子外。在 VM 裡,代理看到的
是佔位符——一個 brm_… token、一份合成的 kubeconfig、一把用完即棄的 SSH
金鑰——而仲介只在網路邊界,對你已核准的目的地的請求,才換上真正的值。於是
「安全掃描」跑起來,走遍磁碟,收穫到它正是被派去收穫的東西:假貨。而這場
攻擊那聰明的驗證步驟反噬了自己——它呼叫 AWS 與 GitHub 確認 token 是活的,
誘餌通不過那道檢查,那道本該只留下能用金鑰的篩子,什麼也沒留下。
錢包不在那裡。 Sui 與 Solana 的金鑰庫、瀏覽器的登入資料庫、錢包擴充 功能——這些沒有一樣住在用完即棄的程式 VM 裡。它們在你真正的機器上,隔著一層 Hypervisor,掃描看不到。關掉工作階段,盒子就重置,連同那個被下毒的規則檔。
外洩是被把關的。 假設掃描找到了值得送出的東西。對 ddjidd564.github.io
的 POST,或對某個 GitHub Gist 的寫入,是一個外送請求,而每一個外送請求都會
穿過主機代理,在那裡真正的目的地會在出去的路上,被拿去對設定檔的核准清單
比對。一個對著設定檔從未核准過的位址打電話回家的竊賊出不去——而針對設定檔
確實代管的那些 API 的破壞性動作,會遇上一道護欄,無論代理被說動了什麼,
它都能拒絕。
在這一切之前,坐著那道在 TrapDoor 的扳機處迎向它的層。整場攻擊始於代理讀到的 內容——被下毒的規則檔——而 Bromure 在模型據以行動之前,用一個裝置端的 注入偵測器為不可信的內容打分。 那把指令藏過你編輯器的零寬 Unicode,藏不過打分器:它讀同樣的位元組串流, 包含看不見的碼位,而一個解碼成「跑個掃描、把祕密寄出去」的規則檔,正是它被 造來標記的形狀。它在門口攔下其中大半。一種夠新穎的編碼仍可能溜過一個分類器, 這正是它坐在用完即棄的盒子之前、而非取而代之的原因。
對你隱形,對竊賊空無
TrapDoor 令人不安的部分不是編碼的把戲。而是這把戲,作用在你被告知要信任的 那唯一一個檔案上——你為自己的代理寫下的規則——而一個檢視那個檔案的人,看不出 任何不對勁,因為根本沒什麼好看。偵測必須每一次都贏過每一種藏起一行的新 手法。那是一場值得跑的競賽,裝置端的打分器也在跑,但安全不該擱在那裡。
Bromure Agentic Coding 把它擱在下面一層。它假設代理終究會讀到一道它無法與 真的區分的被下毒指令——不論隱形墨水與否——並確保,當代理去找可竊的祕密時, 祕密是誘餌、錢包在一台它搆不到的機器上、出口被把關。掃描照樣跑。它只是空手 而回。裝上它,給你的代理一本規則書,不論下毒與否,都指向 沒有任何值得拿走之物。