適用對象:使用 npm(包括 pnpm 與 yarn)安裝 JavaScript 相依套件的開發者、在 VS Code 或其分支中使用擴充功能的人、透過 GitHub Actions 發布套件的維護者,以及 GitHub Enterprise Server 管理員。本文依據 TanStack、Nx 與 GitHub 發布的事後報告與公告撰寫,不涵蓋攻擊技術細節。
開發者今天應該做什麼
檢查 lockfile 與 CI 紀錄中是否有受影響的 TanStack 版本
受影響的套件為 42 個 Router/Start 套件、共 84 個版本,包括 @tanstack/react-router、@tanstack/react-start、@tanstack/router-core 與 @tanstack/history(完整清單見 GitHub 公告 GHSA-g7cv-rxg3-hmpx)。TanStack 表示 Query、Table、Form、Virtual 及其他套件不受影響。除了檢查 lockfile 目前的內容,也要檢查其在 2026 年 5 月 11 日前後的變更紀錄。惡意版本已在數小時內從 npm 移除,因此在該時段內的安裝,可能不會出現在今天的 lockfile 中。在 CI 中,請尋找 5 月 11 日 19:20 UTC 之後執行過安裝的工作。
檢查你是否安裝了 Nx Console v18.95.0
Nx 的事後報告說明如何用 code --list-extensions --show-versions 檢查已安裝的版本(擴充功能 ID 包含 angular-console)。只有 v18.95.0 受影響,且該版本於 5 月 18 日 UTC 12:30 至 13:09 之間可供下載。Nx 要求,凡在該時段內開啟自動更新並安裝 Nx Console 的人,應將該機器視為已遭入侵,無論最終確認的安裝數字為何。事後報告也列出要檢查的檔案與程序(入侵指標);若你受影響,請依照該清單逐一檢查。
若受影響,輪換該機器可存取的所有憑證
TanStack 與 Nx 列出的目標相同:GitHub 權杖、npm 權杖、SSH 金鑰、雲端憑證(AWS、GCP、Azure)、Kubernetes、Vault 權杖,以及任何 .env 檔案的內容。Nx 另外補充:機器上的工具在該時段內可能核發的憑證(臨時雲端憑證、GitHub CLI 權杖等)也應一併考慮,並建議在輪換後考慮對該機器進行完整重建。關於撤銷順序與如何處理駐留的惡意程式,請參閱〈防禦 npm 供應鏈蠕蟲〉中的「若懷疑已感染」一節。
若你維護 npm 套件,請檢查發布紀錄
根據 TanStack,程式碼會尋找受害者所維護的其他套件,並嘗試以相同的注入內容重新發布。若你發布到 npm,請檢查自 5 月 11 日以來,你的套件版本紀錄中是否有你並未發布的版本。
確認你的 GitHub 權杖儲存在電腦的哪裡
根據 Nx,遭竊的憑證是 GitHub CLI 權杖。在該環境中,它儲存在磁碟上的一個檔案內,且以該使用者身分執行的任何程序都能讀取,並在 74 秒內就被用於 GitHub API。請執行 gh auth status 查看你的權杖儲存位置;若它位於純文字檔案中,請考慮改存到作業系統的金鑰圈,或使用只在執行時才注入憑證的密碼管理器整合。事件後,Nx 的政策已禁止在開發者電腦上直接使用 GitHub CLI。關於縮短權杖有效期與縮小權限範圍,請參閱〈防禦 npm 供應鏈蠕蟲〉。
確認你的發布年齡設定確實生效
根據 Nx,遭入侵的貢獻者專案在 .npmrc 中設定了 minimum-release-age=10080(7 天),但該專案固定使用 pnpm 10.14,而此版本不支援該設定,並悄悄忽略了它。pnpm 自 10.16 起才支援。惡意版本在安裝時只有 77 分鐘大,因此有效運作的設定本可以攔下它。請檢查 package.json 中 packageManager 欄位所固定的版本,並讓 CI 驗證其版本足夠新。npm 的對應設定已在〈防禦 npm 供應鏈蠕蟲〉中說明。
GitHub Enterprise Server 管理員:輪換簽章金鑰
5 月 26 日,GitHub 宣布正在輪換金鑰,包括用於簽署 GitHub Enterprise Server 更新套件的金鑰。管理員必須輪換其執行個體中的 GPG 公開金鑰;否則,之後的升級會失敗,並出現檔案不是有效 GHES 套件的錯誤。操作說明與輔助腳本的 SHA256 摘要列於 GitHub 的公告中。GitHub 也要求客戶僅從官方來源下載 GHES 更新,並準備在未來數個月內以更高頻率接收安全更新。GitHub Enterprise Cloud 客戶不需採取任何行動。
套件發布者應在 CI 中檢查什麼
TanStack 與 Nx 的事後報告都具體指出了哪些設定讓攻擊鏈得以通過。以下將這些發現轉換為你可在自己的儲存庫中檢查的設定與政策。
不要在 pull_request_target 下執行 fork 的程式碼
根據 TanStack,一個套件大小檢查工作流程以 pull_request_target 執行,並在其中檢出並建置來自 fork 拉取請求的程式碼。pull_request_target 以基底儲存庫的權限執行,TanStack 指出首次貢獻者的核准閘門不適用於此觸發條件。請僅將它用於不會執行外部程式碼的工作,例如加標籤與留言。事件後,TanStack 已從其 CI 中移除所有 pull_request_target 的用法。
不要在不受信任的工作與發布工作之間共用快取
根據 TanStack,GitHub Actions 快取以儲存庫為單位共用:pull_request_target 的執行與推送到 main 的工作使用相同的範圍。將工作流程的 permissions: 設為唯讀,也無法阻止快取寫入。因此,發布工作流程還原了一個由執行外部程式碼的工作所寫入的快取。事件後,TanStack 停用了其發布管線中的套件快取,並清除所有快取。對於會發布的工作流程,不還原快取是最簡單的界線。
只在需核准的發布工作中授予發布權限(id-token: write)
TanStack 的發布工作流程持有 id-token: write,用於 npm 受信任發布(OIDC)。根據事後報告,惡意發布並非來自工作流程定義的發布步驟;同一次執行中另一階段的程式碼擷取了權杖並直接發布。TanStack 自身的教訓是,受信任發布者的綁定不包含每次發布的審查。請將發布拆分為獨立工作,與建置及測試分開,只讓該工作擁有此權限,並將其置於要求 必要審核者 的 GitHub 環境之後。事件後,Nx 規定發布必須由觸發該執行者以外的人批准。
將第三方 Action 固定到 commit SHA
事件後,TanStack 與 Nx 都將每個 Action 參照固定到 commit SHA,而不是標籤或分支。TanStack 將浮動參照描述為「獨立於本次事件、持續存在的供應鏈風險」。
將發布通知與稽核紀錄導向會閱讀的人
Nx 是透過擴充功能市集在每次上傳時寄出的例行通知信,發現遭竄改的發布版本。一位未預期有發布的維護者認出其異常,並在約 11 分鐘內將其下架。第二個散布管道沒有此類通知,在該管道下架花了約 36 分鐘。同時,遭竊權杖的相關活動(例如刪除工作流程執行紀錄)在稽核紀錄中停留了一週而未被察覺。請確認發布通知會送達團隊中的某人,並確認有人監看稽核紀錄中的工作流程執行刪除事件。
事件經過(依三家組織的公開揭露)
以下所有內容均依 TanStack 事後報告、Nx 事後報告與 GitHub 公告所述。時間為 UTC。
2026 年 5 月 11 日 19:20–19:26
透過 TanStack Router/Start 儲存庫的發布工作流程,42 個套件的 84 個惡意版本被發布到 npm。5 月 11 日 19:46
一位外部研究人員在 TanStack 的儲存庫提交詳細報告。TanStack 開始應變。5 月 11 日 20:43
一名 Nx 貢獻者在一個與 Nx 無關的專案中執行pnpm install,解析到惡意的@tanstack/zod-adapter@1.166.15。根據 Nx,其 GitHub CLI 權杖遭竊取,並在 74 秒內被使用。5 月 11 日 21:03 前
TanStack 已將全部 84 個版本標示為棄用。5 月 11 日 22:13–23:55
npm 從登錄檔移除受影響的 tarball。5 月 15 日
TanStack 發布安全結論:所有目前已發布的版本都是安全的。5 月 18 日 12:30–13:09
利用遭竊的貢獻者存取權,Nx Console v18.95.0 被發布到兩個擴充功能散布管道,隨後被下架。5 月 18 日(週一,美國時間)
GitHub 偵測並遏止一台員工裝置遭入侵的事件,該裝置涉及惡意 VS Code 擴充功能;GitHub 移除了惡意擴充功能版本並隔離該端點。當日及次日,關鍵機密已輪換。5 月 20 日
GitHub 公開說明:其評估為僅 GitHub 內部儲存庫遭外流。5 月 21 日
Nx 發布其事後報告。5 月 26 日
GitHub 更新其公告:正在輪換金鑰,包括 GitHub Enterprise Server 簽章金鑰,並列出管理員應採取的行動。
- TanStack:範圍
- 42 個套件、84 個版本,來自 Router/Start 儲存庫。Query、DB、Store、Table、Form、Virtual 及其他儲存庫未受影響。TanStack 表示沒有證據顯示 npm 權杖遭竊
- TanStack:程式碼做了什麼
- 以安裝時腳本執行,收集雲端、Kubernetes、Vault、npm、GitHub 與 SSH 憑證並送出,並嘗試散播到受害者所維護的其他套件
- TanStack:根本原因
- 以下三者的組合:(1) 在
pull_request_target下建置 fork 的程式碼,(2) 該工作能寫入發布工作流程會還原的快取,(3) 發布工作流程能產生具發布能力的 OIDC 權杖 - Nx:範圍
- 僅 Nx Console v18.95.0(v18.100.0 及之後的版本是安全的)。Nx CLI、官方
@nx/*外掛與 Nx Cloud 未受影響。官方市集統計為 28 次安裝;第二個管道為 41 次下載。Nx 自己的分析顯示約 6,000 次啟用,差距仍在核對中 - Nx:根本原因
- (1) 上游 TanStack 遭入侵,(2) 舊版 pnpm 悄悄忽略發布年齡設定,(3) 磁碟上可讀取的 GitHub CLI 權杖,(4) 允許單一貢獻者發布擴充功能的發布流程
- GitHub:範圍
- 評估為:僅 GitHub 內部儲存庫遭外流。沒有證據顯示存放於這些儲存庫之外的客戶資訊受到影響,例如客戶自身的企業、組織與儲存庫。部分內部儲存庫確實包含客戶資訊,例如支援互動的摘錄
- GitHub:回應
- 移除惡意擴充功能版本並隔離端點。依影響最大者優先,輪換關鍵機密。輪換包括 GitHub Enterprise Server 簽章金鑰在內的金鑰,並要求管理員輪換公開金鑰。表示將在調查完成後發布更完整的報告
閱讀說明:「從 GitHub 取走的儲存庫數量」並非 GitHub 自己的數字
GitHub 的公告提到外流儲存庫的數量,但它將該數字呈現為攻擊者的主張,並只表示其與目前調查結果「方向上一致」。本站不將攻擊者的主張視為事實,因此不重複引用該數字。同樣地,Nx 表示其安裝數字在不同來源之間互相矛盾,仍在核對中。與其依據任何數字判斷,不如根據你在該時段內是否安裝了受影響的版本來做決定。
攻擊鏈可能在哪裡被切斷
1. TanStack CI
外部 PR 程式碼寫入與發布共用的快取
↓→
在此切斷
發布工作流程中不使用 pull_request_target / 不還原快取 / 發布需核准
2. 84 個惡意 npm 版本
透過合法路徑發布,因此看起來很真實
↓→
在此切斷
發布年齡延遲——需工具版本支援該設定
3. Nx 貢獻者的電腦
從磁碟上的檔案讀取 GitHub CLI 權杖
↓→
在此切斷
不以純文字儲存權杖檔案 / 監看稽核紀錄中的刪除事件
4. Nx Console v18.95.0
一人的存取權即可發布擴充功能
↓→
在此切斷
需由觸發者以外的人批准
5. GitHub 員工裝置
惡意擴充功能,隨後內部儲存庫遭外流
↓→
在此切斷
將擴充功能更新視為相依套件(見下一節)
這次沒有證明安全的做法
- 合法的發布路徑與來源證明:TanStack 的惡意版本是經由有效的 OIDC 綁定產生的
- 真實的貢獻者帳號:Nx Console 是以真實貢獻者的存取權發布的
- 發布管道的自動檢查:根據 Nx,遭竄改的版本通過了官方市集的自動驗證
- 已設定但未實際強制執行的設定:發布年齡設定被舊版 pnpm 悄悄忽略
可能切斷攻擊鏈的做法(依事後報告)
- 發布前由第二人批准:Nx 在其他儲存庫上已有此機制,但 Nx Console 上沒有
- 將發布工作流程與快取分離:TanStack 事後停用了快取
- 實際運作的發布年齡延遲:惡意版本在安裝時只有 77 分鐘大
- 有人閱讀例行的發布通知:這是 Nx 唯一的偵測方式
本站觀點:擴充功能自動更新就是自動的相依套件引入
對於 npm 相依套件,「不安裝最近幾天才發布的任何內容」正逐漸成為常見做法。然而,編輯器擴充功能通常預設自動更新,而相同的思維尚未普及。這也是為何 Nx 寫道,凡開啟自動更新的人都應假設已遭入侵。此外,擴充功能會以你的權限,在持有你 GitHub 與雲端憑證的電腦上執行。在持有正式環境或套件發布權限的機器上,可考慮透過 VS Code 的 extensions.autoUpdate 設定關閉自動更新,並在數天後自行套用更新。代價是安全修補較慢,但如同本次事件,在發布後數分鐘內就被下架的版本,單靠延遲就能避開。
另外一點:此攻擊鏈跨越了組織界線。Nx 貢獻者是在與 Nx 無關的專案中安裝了惡意套件,GitHub 員工則是安裝了 Nx 的擴充功能。你的開發機器是你所交付程式碼的每一個專案供應鏈的一部分,而不只是你雇主的供應鏈。
資料來源(公開紀錄)
本文事實來自以下公開來源。我們不涵蓋攻擊技術,也不涵蓋可識別攻擊者身分的資訊。
- TanStack,〈Postmortem: TanStack npm supply-chain compromise〉(2026 年 5 月 11 日發布;5 月 15 日更新)— tanstack.com
- TanStack,〈Hardening TanStack After the npm Compromise〉(事件後的變更)— tanstack.com
- GitHub Advisory Database,〈GHSA-g7cv-rxg3-hmpx (CVE-2026-45321)〉(受影響版本完整清單)— github.com
- Nx,〈Postmortem: Nx Console v18.95.0 supply-chain compromise〉(2026 年 5 月 21 日)— nx.dev
- Nx Console 安全公告 「GHSA-c9j4-9m59-847w」 — github.com
- GitHub,〈Investigation update: GitHub Enterprise Server signing key rotation〉(2026 年 5 月 20 日發布;5 月 26 日更新)— github.blog
- GitHub Security Lab,〈Keeping your GitHub Actions and workflows secure: Preventing pwn requests〉(安全使用 pull_request_target)— securitylab.github.com
- GitHub Docs,〈Managing environments for deployment〉(必要審核者)— docs.github.com
更新紀錄
2026-09-30:首次發布,依據 TanStack 事後報告(5 月 15 日修訂版)、Nx 事後報告(5 月 21 日)與 GitHub 公告(5 月 26 日更新)撰寫。GitHub 表示將在調查完成後發布更完整的報告;屆時我們將更新本頁。
延伸閱讀
- 遭竊 GitHub 權杖被用來鎖定 CI 機密的案例:約 4,800 個 GitHub 帳號遭濫用(2026 年 11 月)
- 較新的遭竄改散布管道案例:《勝利女神:NIKKE》PC 啟動器檔案遭竄改以散布惡意程式
- 相同模式與撤銷順序:防禦 npm 供應鏈蠕蟲
- 避免機密進入儲存庫:使用 gitleaks 在提交前攔截機密 / .env 檔案與 API 金鑰的風險所在
- 透過有效憑證發生的外洩:2026 年的外洩事件是透過有效憑證發生的
- 帳號保護:如何選擇多因素驗證 / SSH 金鑰的最小權限原則
- 竊取的開發者權杖被用來透過官方發布工作流程出貨:LiteLLM 1.107.0 中的惡意程式
- 其他 2026 年事件:2026 年的資料外洩與網路攻擊 / Canvas(Instructure)資料外洩事件