在開(kāi)源生態(tài)高度繁榮的今天,一行代碼、一個(gè)權(quán)限、一款插件,都可能成為引爆供應(yīng)鏈安全危機(jī)的導(dǎo)火索。本文作者親歷了自己維護(hù) 8 年的知名開(kāi)源項(xiàng)目 Neutralinojs 遭遇惡意攻擊,且他的經(jīng)歷并非個(gè)例,而是一個(gè)典型信號(hào):供應(yīng)鏈攻擊已經(jīng)從“攻擊代碼”,演變?yōu)椤肮粜湃侮P(guān)系”。它不再依賴傳統(tǒng)Bug,而是潛伏在協(xié)作者權(quán)限、開(kāi)發(fā)流程乃至 AI 插件生態(tài)之中,悄無(wú)聲息地發(fā)生。
原文鏈接:https://levelup.gitconnected.com/my-8-year-old-open-source-project-was-a-victim-of-a-major-cyber-attack-24af7eb3a82b
作者 | Shalitha Suranga 編譯 | 鄭麗媛
出品 | CSDN(ID:CSDNnews)
很多時(shí)候,我們總是擔(dān)心想象中的風(fēng)險(xiǎn),卻很少直面現(xiàn)實(shí)中的恐懼。可當(dāng)你最擔(dān)心的事以完全意想不到的方式發(fā)生時(shí),你該如何應(yīng)對(duì)?
最近,我就親身經(jīng)歷了這一切。我在 GitHub 上維護(hù)的一個(gè)熱門開(kāi)源項(xiàng)目,卷入了一場(chǎng)大規(guī)模軟件供應(yīng)鏈攻擊。而這次被攻破的原因非常特殊 —— 竟是我們開(kāi)發(fā)工作流里的一個(gè)Bug。
如果你也是開(kāi)發(fā)者,那么這種事情完全有可能發(fā)生在你身上。運(yùn)氣差一點(diǎn),你耗時(shí)十年的心血可能在一天之內(nèi)毀于一旦,項(xiàng)目口碑也會(huì)徹底崩塌,再也無(wú)法挽回。
下面,就是我開(kāi)源生涯中最驚險(xiǎn)的一次事故,以及我是如何在安全團(tuán)隊(duì)和一點(diǎn)點(diǎn)“運(yùn)氣”的幫助下,救回這個(gè) 8 年老項(xiàng)目的。
![]()
![]()
項(xiàng)目背景:一個(gè)對(duì)標(biāo) Electron 的輕量級(jí)方案
這個(gè)項(xiàng)目叫 Neutralinojs。它是一個(gè)輕量級(jí)的跨平臺(tái)桌面應(yīng)用開(kāi)發(fā)框架,2018 年我和其他幾位開(kāi)發(fā)者一起啟動(dòng)了這個(gè)項(xiàng)目,但很快就變成了我一個(gè)人維護(hù)。
過(guò)去幾年,我投入了大量時(shí)間打磨這個(gè)項(xiàng)目,并逐步建立起社區(qū)生態(tài),它曾三次入選 Google Summer of Code(GSoC):2022、2024、2026 年。
簡(jiǎn)單來(lái)說(shuō),它的定位就是:Electron 的輕量替代方案。如今已有成千上萬(wàn)的跨平臺(tái)應(yīng)用基于它構(gòu)建,開(kāi)發(fā)者社區(qū)還在持續(xù)壯大,核心貢獻(xiàn)者也一直在積極推動(dòng)項(xiàng)目迭代。
這個(gè)項(xiàng)目一直強(qiáng)調(diào)兩件事:極簡(jiǎn)設(shè)計(jì)和性能優(yōu)先。對(duì)于很多程序員來(lái)說(shuō),Neutralinojs 不僅是工具,更是一種工程理念。
![]()
災(zāi)難的開(kāi)始:一條 LinkedIn 私信
我平時(shí)不怎么刷 LinkedIn,但會(huì)認(rèn)真查看私信 —— 很多人會(huì)來(lái)咨詢 Neutralinojs、GSoC,或是邀請(qǐng)我參加技術(shù)分享。
3 月 5 日早上,我收到了一條來(lái)自 OpenSourceMalware(OSM)安全團(tuán)隊(duì)成員的 LinkedIn 私信。內(nèi)容大概是:
“你的主代碼倉(cāng)庫(kù)已經(jīng)被植入惡意 JavaScript 代碼,我們已經(jīng)提交了一個(gè) PR 用于清除它。”
看到這條消息,我整個(gè)人直接懵了。因?yàn)槲易顡?dān)心的事情就是:自己誤合并了帶惡意代碼的 PR,所以甚至連 GitHub Dependabot 自動(dòng)生成的 PR,我都會(huì)仔細(xì) review。
我的第一反應(yīng)是:我的 GitHub token 被盜了?還是賬號(hào)被入侵了?但我對(duì)安全一向很謹(jǐn)慎,自認(rèn)賬號(hào)幾乎不可能出問(wèn)題。
但很快,我就確認(rèn)代碼庫(kù)是真的被入侵了:項(xiàng)目四個(gè)核心倉(cāng)庫(kù)全部被注入惡意 JavaScript 代碼。而且攻擊手法非常隱蔽:這些惡意代碼經(jīng)過(guò)重度混淆,還利用大量空格巧妙隱藏,在 GitHub 代碼查看器里,肉眼幾乎無(wú)法察覺(jué)異常。
顯然,這不是普通攻擊,這是精心設(shè)計(jì)的供應(yīng)鏈攻擊。我立刻和 OSM 成員協(xié)作,第一時(shí)間保障貢獻(xiàn)者、應(yīng)用開(kāi)發(fā)者和用戶的安全。
![]()
緊急止血:第一時(shí)間做了什么?
雖然當(dāng)時(shí)還不清楚這段惡意代碼的破壞力,但我直接按最高危漏洞處理:
(1)合并 OSM 的 PR,清理所有倉(cāng)庫(kù)中的惡意載荷;
(2)刪除已構(gòu)建的 nightly 版本,禁用 nightly 構(gòu)建工作流;
(3)吊銷我之前創(chuàng)建的所有 GitHub Token;
(4)禁止所有受影響倉(cāng)庫(kù)默認(rèn)分支的直接推送—— 這正是我們 Git 工作流里最致命的漏洞!
(5)檢查 GitHub 發(fā)布?xì)v史和 NPM 包(@neutralinojs/neu、@neutralinojs/lib);
(6)在所有受影響倉(cāng)庫(kù)添加重大安全公告,并通過(guò) Discord 高優(yōu)先級(jí)消息通知社區(qū);
(7)啟動(dòng)全面安全審計(jì):檢查代碼、活躍 Fork、倉(cāng)庫(kù)設(shè)置、GitHub Actions、開(kāi)發(fā)工具等所有關(guān)聯(lián)環(huán)節(jié)。
以上這些的核心目標(biāo)只有一個(gè):阻止惡意代碼繼續(xù)擴(kuò)散。
根據(jù) OSM 的報(bào)告 + 我的分析,最終結(jié)論如下:
攻擊發(fā)生在 3 月 2 日很短一段時(shí)間內(nèi);
只有 Neutralinojs 組織下的 4 個(gè)倉(cāng)庫(kù)被強(qiáng)制推送、篡改歷史 Git 提交,其他倉(cāng)庫(kù)安全;
所有 GitHub 發(fā)行版和 NPM 包都是干凈的;
只有在 3 月 2–5 日之間 pull 代碼的人可能中招;
攻擊源頭來(lái)自朝鮮,惡意代碼會(huì)連接 C2(指揮控制)服務(wù)器(部署在 Vercel,已被移除)。
換句話說(shuō):這是一場(chǎng)差一點(diǎn)就炸掉整個(gè)生態(tài)的攻擊!
幸運(yùn)的是,在 OSM 團(tuán)隊(duì)支持下,我通過(guò)清理 Git 記錄、開(kāi)啟 GitHub 分支保護(hù)規(guī)則,徹底解決了這次危機(jī)。
![]()
破案時(shí)刻:真正的入侵路徑
盡管如此,但事情還沒(méi)結(jié)束,我開(kāi)始化身“偵探”,繼續(xù)調(diào)查這件事情的源頭:攻擊者居然還能訪問(wèn)其他倉(cāng)庫(kù)(雖然主倉(cāng)庫(kù)已經(jīng)禁止直接推送),這到底是怎么做到的?
我一開(kāi)始以為是自己的某個(gè) GitHub Token 被盜,但事實(shí)并非如此。我發(fā)現(xiàn):注入惡意代碼的強(qiáng)制推送,來(lái)自 Neutralinojs 組織非常早期的一位“老成員”,而且他的 GitHub 賬號(hào)竟然還擁有所有倉(cāng)庫(kù)的寫入權(quán)限!
我立刻吊銷了他的權(quán)限,重新檢查所有倉(cāng)庫(kù),并同步給 OSM 團(tuán)隊(duì)。
隨后,我在他的個(gè)人 GitHub 倉(cāng)庫(kù)里也找到了同款惡意 JavaScript 載荷——真相大白:是他的賬號(hào)被攻陷了,不是我的 Token 或賬號(hào)泄露。
我馬上聯(lián)系他,他回復(fù):
“我剛裝了 OpenClaw,還給了 GitHub 權(quán)限,可能就是這個(gè)原因。”
事后,OSM 發(fā)布了最終報(bào)告,重新掃描所有倉(cāng)庫(kù)后確認(rèn):Neutralinojs 代碼庫(kù)已完全安全。我也同步通知了所有貢獻(xiàn)者,并給可能受影響的開(kāi)發(fā)者提供了修復(fù)方案。
一天后,這位賬號(hào)被黑的“老成員”確認(rèn):他是最近名為 ClawHavoc 供應(yīng)鏈攻擊的受害者之一,病毒通過(guò)被入侵的 OpenClaw 插件擴(kuò)散。目前,同款惡意 JavaScript 載荷仍在通過(guò)其他被盜賬號(hào)在 GitHub 上擴(kuò)散,并且出現(xiàn)了多個(gè)變種。
據(jù) OSM 披露:該惡意軟件會(huì)從區(qū)塊鏈交易中獲取 C2 服務(wù)器地址。即便主服務(wù)器被 Vercel 下架,攻擊者依然可以新建服務(wù)器,并把地址寫入?yún)^(qū)塊鏈,繼續(xù)控制受害者電腦。
![]()
給所有開(kāi)源維護(hù)者的安全建議
根據(jù) OSM 的說(shuō)法,這類跨平臺(tái)、基于 JavaScript、利用區(qū)塊鏈獲取 C2 地址的供應(yīng)鏈攻擊正在快速激增,用 Linux / Mac 也并不代表 100% 安全。
我認(rèn)為,以下是保護(hù)你自己和項(xiàng)目的關(guān)鍵建議:
(1)立刻開(kāi)啟分支保護(hù)規(guī)則,這是做正經(jīng)項(xiàng)目的第一步;
(2)永遠(yuǎn)不要讓 Git 明文存儲(chǔ) Token,Linux 下可以用 libsecret 安全存儲(chǔ)憑證;
(3)定期檢查倉(cāng)庫(kù)寫入權(quán)限,前成員離開(kāi)立即回收權(quán)限;
(4)謹(jǐn)慎選擇依賴,下載前先看安全警報(bào);
(5)仔細(xì)閱讀所有依賴的更新日志與安全說(shuō)明;
(6)最小權(quán)限原則,不要無(wú)腦給全量權(quán)限;
(7)不要盲目復(fù)制粘貼網(wǎng)上代碼,尤其是終端命令;
(8)所有重要賬號(hào)(GitHub、NPM 等)務(wù)必開(kāi)啟 2FA。
在此之前,我不是沒(méi)見(jiàn)過(guò)病毒、木馬、社會(huì)工程學(xué)等攻擊,但這種形式的供應(yīng)鏈攻擊還是第一次親身經(jīng)歷——現(xiàn)在的惡意軟件已經(jīng)進(jìn)化到恐怖的程度:你只需要執(zhí)行一條 git clone、npm install,甚至只是把某人加進(jìn)倉(cāng)庫(kù)協(xié)作,電腦就可能中招。
2026 年,數(shù)字世界的每一步操作都要小心。供應(yīng)鏈攻擊,已是這個(gè)時(shí)代開(kāi)發(fā)者最可怕的敵人。
同時(shí)也要謹(jǐn)慎使用 AI,使用前必須花時(shí)間了解它的工作原理。在我看來(lái),OpenClaw 的插件生態(tài)設(shè)計(jì)非常“危險(xiǎn)” —— 居然把原始系統(tǒng)命令存在 Markdown 文件里來(lái)擴(kuò)展 AI 能力!
這一次,是 OSM 團(tuán)隊(duì)救了 Neutralinojs。現(xiàn)在項(xiàng)目所有倉(cāng)庫(kù)已經(jīng)完全干凈,我們將繼續(xù)沖擊 2026 年 GSoC!
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.