返回所有文章
發佈於 · 作者 Renaud Deraison

那道指令的開頭是 npm install

2026 年 8 月 24 日,Cato Networks 的 CTRL 團隊公布了一場攻擊行動:它買下「codex macos download」的 Google 贊助搜尋結果,把開發者帶到一個偽裝成 OpenAI Codex 入口的 Google Sites 頁面,再請他們把一道指令貼進終端機,而那道指令的第一行,是真正的 Codex npm install。那一行之後的所有東西都是 base64。Bromure Agentic Coding 從不讓任何人去尋找程式設計代理:安裝指令是 Bromure 自家映像目錄裡的一段固定字串,它在用完即棄的 Linux VM 中執行,VM 裡的憑證都是誘餌,而只要把未匹配的對外流量設為拒絕,載入器的那三次取得就永遠離不開這台機器。

兩年來,業界一直在為程式設計代理「裝了什麼」建立控制。這場行動往前多走一步, 轉而汙染你「怎麼安裝」程式設計代理。那個步驟沒有登錄檔,沒有鎖定檔,也沒有 來源證明。它只有一個搜尋框、一個看起來沒問題的頁面,以及你自己放在鍵盤上的手。

一位開發者想在自己的 Mac 上試試 OpenAI 的 Codex CLI,於是在 Google 打下 codex macos download。第一筆結果是贊助的,排在 OpenAI 自家連結之上。它通往一個 乾淨的下載入口,標誌對、字體排版也對,託管在 sites.google.com 上。頁面說:打開 終端機,把這個貼上去。

他貼了。指令以 npm install 開頭,套件名稱也是對的。

8 月 24 日,Cato Networks 的研究團隊 CTRL 發表了 這場行動的分析, 同日獲得 Infosecurity MagazineSiliconANGLETechzine 轉載。最終酬載是一支 macOS 竊密程式。真正值得寫成報告的,是它的投遞方式。

頁面由 Google 託管,誘餌由別人託管。

Google Sites 是個網站產生器。任何人只要有帳號,就能在 Google 網域上擁有一個頁面, 而憑證、鎖頭圖示和網址的前半段,全都屬於 Google。那就是被租來的信任。

頁面本身什麼也沒有。Cato 在上面完全沒找到惡意程式碼。誘餌是透過一個指向攻擊者 基礎設施的 iframe 送達的;依 Cato 的分析,它還經由 Google 的靜態內容代理轉送, 所以連第二段跳轉看起來都像是 Google 在抓取什麼東西。Techzine 點名了其中兩個 iframe 主機:bright-links[.]comswiftsaverfin[.]com

這樣的切割替營運者買到兩件事。看得見的那個頁面永遠不變,所以它不會觸發信譽系統, 也不會被重新審查;而他們可以隨時在 iframe 的另一側替換酬載。Cato 數出三組彼此 獨立的基礎設施,其中第三組重複使用了第一組的一個 iframe 主機。

其餘部分讀起來就像一場成熟的廣告詐欺行動。活的誘餌放在一個混淆過的路徑 /codexx/ 底下,而 /codex/ 送出的是無害的東西。營運者會對訪客做指紋辨識,任何看起來不像 合理 macOS 目標的訪客,都只會看到良性內容——那是他們對研究人員與沙箱的回答。網域 會輪替。酬載網址也會變。

第一行是真的

ClickFix 不會送你一個檔案。它給你一道指示,讓你自己把酬載搬過邊界。用 Techzine 的話說:「沒有任何檔案被下載,自然也沒有防毒方案能攔。」

貼上的指令,開頭是一段看起來完全合法、屬於 Codex 的 npm install 字串。整個把戲 就在這裡。一個正要安裝 Node CLI 的開發者看到 npm install,看到自己搜尋的套件 名稱,大腦就把這一行歸檔成正確。後面那團 base64 只隔著一個 shell 運算子,就在 同一行上,在複製框的折線之外。當一道指令的前半段正是你預期的指令時,你不會去讀 它的後半段。

解碼之後,它會抓一支遠端指令稿,再把它導進 zsh。接下來是三個階段。

第一階段是一支用死程式碼和未使用變數灌水的 shell 指令稿,裡面包著一團編碼過 的資料,最後交給 eval。灌水的存在,是為了打敗特徵比對,也是為了讓隨手翻閱檔案 的人放棄。

第二階段在做任何其他事之前,先帶著 event=pasted 這個參數向攻擊者回報。那是 一張投遞回執。另一端有人正在量測他們各個到達頁的「貼上率」,就像行銷人員量測 轉換率一樣。

第三階段把二進位檔下載到 /tmp/helper,執行 xattr -c 移除 macOS 加在所有 來自網路之物上的隔離屬性——正是這一步讓 Gatekeeper 的警告消失——接著標記為可執行 並啟動它。這支二進位檔是通用 Mach-O,所以在 Intel 和 Apple Silicon 上都能跑。

Cato 指出,營運者仍在持續開發這支載入器。較早的樣本使用帶壓縮的 base64;較新的 則使用 AES 加密的 gzip 容器,其金鑰是從散落在指令稿各處的變數重新組合而成。

至於最終酬載,Cato 把這套投遞框架連結到 Atomic macOS Stealer:載入器網址的 結構、遙測請求的形狀、/tmp/helper 這個暫存路徑、xattr 的移除、以更新為主題的 酬載網址。他們稱這些重疊之處既強烈又一致,但止步於為那支二進位檔命名——這是正確 的判斷,而且在轉述時值得一併保留。

投遞:受害者所見的一切codex macos download贊助結果,排在OpenAI 官方連結之上sites.google.comCodex 入口的仿冒品,本身沒有惡意程式碼iframe:真正的誘餌bright-links[.]comswiftsaverfin[.]com「開終端機,貼上這段」沒有下載開發者讀到的唯一一行npm install ... codex ...; base64 -d ... | zsh執行:三個階段,三次對外取得1 · 載入器用死程式碼與未用變數灌水的 shell 指令稿eval "$blob"2 · 回執遙測信標回傳?event=pasted營運者的轉換指標3 · 酬載/tmp/helperxattr -c ; chmod +x通用 Mach-O
從搜尋框到執行中二進位檔的完整鏈條。其中任何一環都沒有漏洞利用:一則贊助廣告、一個什麼都不含的 Google 託管頁面、一個什麼都含的 iframe,以及一個以貼上動作親手把酬載搬過邊界的人。受害者唯一看得到的那道指令,開頭是真正屬於 Codex 的 npm install 行;跟在後面的 base64 才去抓第一階段。第二階段的 event=pasted 信標,是營運者自己的投遞回執。

掃描器上游的那一步

把業界花了兩年、為程式設計代理打造的那些控制排開來看。登錄檔信譽掃描。鎖定檔與 完整性雜湊。建置來源與證明。SBOM。新套件版本的最短存在時間閘門。對生成程式碼做 靜態分析。它們都有效,而且都從同一個假設出發:開發者已經有一套能用的工具鏈, 風險在下游,在他拿它來做什麼。

這場行動坐在這一切的上游。這裡的偽造品是代理本身,而它在任何登錄檔之前、 任何鎖定檔之前就已抵達,以一道開發者用自己的手打進自己終端機的指令抵達。掃描器 沒有任何成品可以評分,因為那個成品是網頁上的一句話。

鎖定目標是這門經濟的另一半。會去競標 codex macos download 的人,買的是一台屬於 「此刻正在架設程式設計代理」之人的機器:一台在一小時內就會裝著 API 權杖、SSH 金鑰、一份 ~/.aws/credentials 和一枚 GitHub PAT 的機器,而這些東西竊密程式全都 知道去哪裡找。安裝的那一刻,是待在現場最便宜的時間點。

我們寫過這件事的反面:在 FakeGit 與 AgentBaiting 裡,是代理 去搜尋,再把安裝步驟遞給人。這裡則是去搜尋。兩者都成立,因為「先發現、再貼上」 就是軟體被安裝的方式,而這個迴圈的兩端都沒有掃描器坐鎮。

安裝指令從哪裡來

Bromure Agentic Coding 沒有這樣的迴圈,原因就在代理是從哪裡 來的。

你不會去尋找程式設計代理。Codex 是設定檔 Agents 面板裡的一個開關,就在 Claude Code 和 Grok Build 旁邊。把它打開,挑好它怎麼驗證身分,下一次工作階段開始時代理 就在那裡了,在設定檔的 VM 內某個 kitty 分頁中執行。

那個開關背後是一段固定字串。Bromure 從自家目錄佈建基礎映像,而 Codex 的條目只有 一行:

npx --yes @socketsecurity/cli npm install -g --silent @openai/codex

Claude Code 依同樣的模式是 @anthropic-ai/claude-code,Kimi Code 是 @moonshot-ai/kimi-code。套件名稱是編譯進應用程式的,不是被發現的。登錄檔是 registry.npmjs.org,不是某個 iframe 指定的任何主機。安裝過程被包在 socket.dev 的 CLI 之外,而取得動作會經由主機的 MITM 代理送出,設定檔的 Supply Chain 政策就在那裡生效:預設開啟的兩天存在時間閘門,加上 OSV 查詢、socket.dev 或 Delpi 過濾,以及你可以打開的安裝指令稿剝除。

那條路徑沒有搜尋結果,也沒有可供冒充的頁面。攻擊者花錢去汙染的那個管道,根本不在 這套工作流程裡;而「不存在」不是一個你得記得去操作的控制。

用一般方式安裝誰決定成品的名字?贏得廣告競價的那個人誰負責提供?仿冒頁面上的一個 iframe執行的是什麼?第一行之後的任何東西在哪裡?你的 Mac、你的使用者帳號,旁邊就是~/.ssh · ~/.aws · ~/.git-credentialsGatekeeper 被 xattr -c 消音四個沒有答案的問題,由陌生人代答。在 Bromure 設定檔中啟用誰決定成品的名字?@openai/codex,來自映像目錄誰負責提供?registry.npmjs.org,經由主機代理執行的是什麼?一條編譯進去的指令,沒有自由文字在哪裡?一台用完即棄的 Linux VM,早在這場搜尋之前就建好 — 裡面沒有金鑰,憑證都是誘餌,對外流量受管制同樣四個問題,在你問之前就已回答。
取得程式設計代理的兩種方式。左邊,取得這一步就是一個搜尋框和一顆複製按鈕:成品的名字、提供它的主機、以及安裝它的指令,全都由贏得廣告競價的人決定,而結果會跑在那台裝著開發者金鑰的 Mac 上。右邊,成品名稱編譯進應用程式,登錄檔固定,取得動作在主機代理處被過濾,安裝則在一台早在這一切開始之前就建好的用完即棄 VM 中執行。

那就照樣貼上看看

架構必須撐過有人無視它的那一天。把這場行動拿過來,讓它贏,然後帶著它走一遍設定 檔:有人找到那個假入口,複製了指令,把它貼進自己做代理工作的終端機——在 Bromure Agentic Coding 裡,那是 VM 內的一個 kitty 分頁。

那支二進位檔跑不起來。 通用 Mach-O 是 macOS 的執行檔。客體是 Ubuntu。xattr 不是 Linux 指令,而 /tmp/helper 是一個位在「本來就是要被丟掉」的系統磁碟上的 路徑。Resources → Storage 提供給 /home/ubuntuErase home…,以及 Reset to base…——從共用、唯讀的基礎映像重新複製工作區的系統磁碟。

那三次取得出不去。 這條鏈的每個階段都需要網路:base64 解碼後那個拉取第一階段 的網址、event=pasted 信標,以及酬載下載。Guardrails → Outbound connections 是一張 pf 風格的規則表:動作、協定(tcpudpwebany)、主機或 CIDR、 連接埠,而 web 還可以列 HTTP 方法;由上往下比對,第一個命中者勝出,而 Unmatched traffic 可設為 Allow 或 Deny。把它設成 Deny,再列出你工作真正需要的 主機就好。bright-links.com 不在其中。Bromure 在主機端、在虛擬交換器與代理裡強制 執行這張表,所以客體對自己環境做的任何事,都改變不了答案。

值得坐下來細看的是第二階段。event=pasted 是營運者的轉換指標,是那個告訴他們某個 到達頁有效、而且有多有效的 ping。當這個請求死在主機上,他們拿到的不是一份感染 失敗報告。他們拿到的是沉默,而沉默讀起來就像一次沒有轉換的廣告曝光。

竊取拿回去的是佔位符。 Atomic 這一級的竊密程式,盯的是瀏覽器資料、加密錢包, 以及——在開發者機器上——憑證。在 Bromure 的設定檔裡,真正的值從來不會進入 VM。 通用 API 金鑰是以環境變數匯出的 brm_… 假值,由主機代理在傳輸途中替換掉。 kubeconfig 是合成的,搭配用過即丟的用戶端憑證。AWS 請求會在主機端重新簽署,所以 任何繞過代理的東西都會拿到 InvalidSignatureException~/.docker/config.json 裡放的是一團假的 base64。私鑰 SSH 金鑰根本不在裡面等著被讀: 它們從來就不在。逐一為憑證打開 Require approval to use,每一次替換就會變成一個主機端對話框,附帶一段有時限的 授權:五分鐘、一小時,或這次工作階段的其餘時間。一個設定檔最多只分享你挑選的八個 資料夾,所以 Mac 的其餘部分並不是「多走幾層目錄」就能到的地方。

關聯分析早就在你螢幕上了。 Cato 自己的結論是,這場行動的任何單一階段都不會 讓它現形;要偵測到它,得把贊助搜尋的投遞、內嵌的網頁內容、終端機裡的執行,以及 對外活動放在一起關聯。當你的證據分散在瀏覽器、shell 和網路側錄裡,那是個難題。 在設定檔裡,它只是一個視窗:Security Log(Window → Security Log…)是一張 主機端的單一時序表格,記錄套件判定、防火牆決策、憑證替換與提示注入偵測。客體 程式碼無法編輯它,因為客體程式碼根本碰不到它。

把它打開

存在時間閘門預設就是開的,設在兩天。其他層次都是設定,而且值得花兩分鐘: Guardrails → Outbound connections,把 Unmatched traffic 設成 Deny,再為你 工作需要的主機建一份允許清單。Supply Chain → OSV vulnerability check,如果你 有金鑰,再加上 socket.dev 或 Delpi 過濾,還有安裝指令稿剝除。Credentials → 對任何能花錢或能刪資料的東西打開 Require approval to use。然後把 Security Log 視窗開在第二台螢幕上放一個星期,看看你的建置到底都在跟誰說話。

贊助搜尋結果還會繼續當那道前門,受信任網域上的網站產生器也還會繼續出租門廊。 Google 會下架這些頁面,然後又會有三個新的立起來,因為這門生意的算式是「每次點擊 幾塊美金」對上「一台裝著雲端憑證的開發工作站」。 安裝 Bromure Agentic Coding,從設定檔編輯器而不是下載頁啟用你 的代理,讓下一道被貼上的指令,落在一台生來就是要被丟掉的機器裡。