AIセキュリティ

看不見的程式碼會被執行|GlassWorm打破了「審查就能擋下來」這個前提

發布2026-08-13濱本 隆太

畫面完全不顯示的Unicode字元裡,被嵌入可執行的程式碼。這類攻擊GlassWorm已經被確認。它經由VS Code擴充功能自我擴散,安裝次數達到35,800次。為什麼人眼看不到、會在哪些場合踩到,以及在目視審查失效的前提下該怎麼守,整理如下。

看不見的程式碼會被執行|GlassWorm打破了「審查就能擋下來」這個前提
分享

您好,我是TIMEWELL的濱本隆太。

畫面完全不顯示的字元裡,裝著會被執行的程式碼。

這樣寫聽起來像變魔術,但確實發生了。攻擊名叫GlassWorm,經由開發者裝在編輯器裡的擴充功能擴散開來。

這次棘手的地方,不是受害規模,而是它把前提打破了。我們一直靠「人把程式碼讀過再核准」這套機制來守軟體安全。讀不到的東西,既不能核准,也不能駁回。

發生了什麼

先把事實抓穩。2025年10月18日,Koi Security偵測並公布1

遭植入的是VS Code擴充功能。在散布管道OpenVSX等市集上,出現了被塞進惡意程式碼的擴充功能。已確認遭植入的擴充功能為16個,總下載次數為35,800次1

這些擴充功能大致做了這些事1

  • 竊取npm、GitHub、OpenVSX、Git的驗證資訊
  • 49種加密資產錢包擴充功能為對象取資訊
  • 在開發者的裝置上架起SOCKS proxy,當成攻擊端通訊的中繼點
  • 隱密安裝VNC伺服器,讓裝置處於可被遠端操作的狀態

而最重的一點是:用偷來的驗證資訊,再去汙染別的套件與擴充功能1。一個開發者中招,他擁有發布權限的資產就會變成下一個感染源。**它會自我擴散。**這被認為是VS Code擴充功能上首次被確認的行為2

認真面對 AI 資安訓練

為期兩天的密集課程,課程設計依循 OWASP、NIST、ISO 42001 與日本經產省指引。經營層與實務人員可分開受訓。

為什麼人眼看不到

技術核心在這裡。我會寫仔細一點。

用到的是異體字選取器(Variation Selector)這種Unicode字元。範圍是U+FE00到U+FE0F(16個字元),以及U+E0100到U+E01EF(240個字元)。GlassWorm主要用的是後者,可以表達256種值,因此能直接對應0到255的位元組值3

異體字選取器是用來指定同一個字要用哪一種外觀的字元。以漢字為例,同一個字有多種字形時,它會指示「用這一款來顯示」。**也就是說,它本身什麼都不畫出來。**它是關於前一個字該怎麼顯示的指令,自己沒有可顯示的內容。

所以在編輯器裡,看起來就是什麼都沒有的一行。GitHub的差異顯示也一樣。行看起來是空的,就算裡面塞了數百個字元,也看不出來3

執行的機制是這樣3

  1. 從每個字元的碼位,用計算取出位元組值
  2. 把取出的位元組排起來,組出Base64字串
  3. 解碼之後得到JavaScript原始碼
  4. 交給eval執行

也就是說,隱形字元本身是資料,另外有一段短程式碼把它組起來再跑。對攻擊者來說,等於把本體藏進「看不見的資料」,讓眼睛看得到的部分顯得無害。

會在哪些場合踩到

舉幾個具體情況。沒有一件是在做什麼特別的事。

場合1。安裝擴充功能的時候。

在編輯器裡找擴充功能,挑下載次數多的來裝。這是最直接的路徑。GlassWorm裡受害最大的那個擴充功能,安裝次數超過3萬5,000次1。**熱門,不代表安全。**反而越熱門,被接管之後的傷害越大。

而且這次是原本正規的擴充功能,後來才被植入。安裝當下沒有問題,也會在自動更新時進來。「裝的時候有確認過」擋不住。

場合2。審查PR的時候。

打開同事送出的PR,用眼睛追差異。**看起來像多了一行空行。**沒多想就核准。這樣就過了。

這裡最可怕。不是審查者夠不夠專心的問題。**看不見的東西,再怎麼仔細看也看不見。**越資深越容易判斷「差異很小所以安全」,有時反而會反過來害到自己。

場合3。相依套件被更新的時候。

更新npm套件。看一下lockfile的差異。內容不會去讀。**本來就沒有人能每次把幾萬行都讀完。**上游被植入的話,就會原封不動進到自家的建置。

場合4。讓AI寫程式碼、讀程式碼的時候。

這是新的路徑。把儲存庫交給AI程式碼代理去處理。代理是把檔案當文字來讀的。**隱形字元以文字來說,是正常存在的。**人看不見,也不會出現在AI的產出裡。有時就這樣被複製到下一個檔案。

開發工具本身成為感染路徑的結構,我在AI工具成為感染路徑的時代裡用TanStack的案例寫過。AI建議了根本不存在的套件名稱,則在Slopsquatting

撤不掉的指揮系統,這個新意

還有一點讓處理變難:C2(指揮伺服器)放在哪裡

GlassWorm把接收指令的入口做成三層1

主系統是Solana區塊鏈的交易備註。寫進區塊鏈的資訊,本質上事後刪不掉。**就算通報也停不了的指揮系統。**以往那套「把惡意網域下架」「把IP封鎖」在這裡無效。

次要系統是直接連到攻擊者的伺服器,再往下還準備了把指令編碼進Google日曆活動名稱的備援路徑1。備援準備到這個程度,代表這是認真在營運。

看到這個結構就會明白,只把散布來源停掉,事情不會結束。已經進到裝置裡的東西,會繼續去取指令。

把目視審查停掉,才是對策

那要做什麼。方針很清楚。把依賴人眼的檢查,換成機器的檢查。

第一。在本機檢查過,再送出PR。

若是Node.js環境,用下面這條指令就能檢查隱形字元4

npx anti-trojan-source src/index.js

把它變成提交前的習慣。本機就擋下來的話,不會消耗審查者的時間。

第二。在CI用機器擋下來。

更穩的是這一步。若是GitHub Actions,就插入這樣的步驟4

- name: Scan for invisible Unicode attacks
  run: npx anti-trojan-source --files='**/*.{js,ts,jsx,tsx}' --json

偵測到就讓建置失敗。**在人核准之前,先由機器停住。**處理的語言增加時,再把副檔名加上去。也可以做成ESLint外掛,納入既有的檢查4

這裡重要的是,不要把「小心一點」當成對策。這次攻擊的設計,就是注意力擋不住。靠注意力擋不住的東西,只能靠機制擋。

第三。把驗證資訊輪替,並且減少。

GlassWorm的擴散,燃料就是偷來的驗證資訊。定期輪替npm、GitHub、OpenVSX的token。然後把沒用到的token從開發機刪掉4。個人開發機裡留著好幾年前的token,其實相當常見。就算只盤點一次,擴散的燃料也會變少。

第四。把擴充功能當成資產來管。

停止各人隨意安裝的狀態,由組織掌握現在裝了什麼。不只是導入時審查,因為存在更新之後才被植入的路徑,必須持續看。「裝的時候有確認過」,對這次這種事後植入沒有效。

讓AI讀程式碼的時代,這個洞會怎麼作用

最後談一點再往前的事。

沒有人讀過的程式碼,比例接下來一定會增加。AI寫、AI讀、AI審查。那時,「人眼看不見的字元」會變成誰的檢查都勾不到的區域

AI可以把隱形字元當文字處理,但**不保證會把它當成異常來回報。**沒有人保證它會說「這一行排了240個異體字選取器」。就字元來說,那是正當的Unicode,連損毀的資料都算不上。

所以,這項檢查應該放在自動化管線裡。不依賴人的審查,也不依賴AI的審查,用決定性的規則擋下來。看位元組序列,出現非預期的字元就停。就這樣。

老實說,這次攻擊最讓我卡住的,不是技術有多高深,而是著眼點。Unicode的異體字選取器,是為了讓多語文字正確顯示才存在的規格。**為了善意的相容性而預留的空隙,原封不動變成藏匿處。**不是找到新的弱點,只是把既有規格的用法挪偏了一點。

而且,這不是第一次。

2021年,劍橋大學的Nicholas Boucher與Ross Anderson公布了「Trojan Source」。那次濫用的是Unicode的雙向文字控制字元,也就是為了讓阿拉伯文、希伯來文這類由右至左書寫的語言正確顯示而存在的規格。它只在顯示層把token的排列順序對調,就能讓人讀到的程式碼,和編譯器解讀的程式碼,變成兩回事5

影響範圍很廣,C、C++、C#、JavaScript、Java、Rust、Go、Python這些主要語言的編譯器都中招。被指派的編號是CVE-2021-42574與CVE-2021-426945

前面介紹的檢查工具名叫anti-trojan-source,正是為了對抗那次攻擊才做的。五年前的防護工具,對這次攻擊照樣有效。手法不同,但「顯示與實體錯開」這個洞的形狀是一樣的。

這種形狀的攻擊,大概還會在別的規格上再出現。異體字選取器、雙向控制、零寬字元、私用區。Unicode裡有不少「不顯示、但有效的字元」,全部都是候選。所以對策也該先一般化:**在某個地方,用機器確認「自己正在讀的,和機器正在執行的,是同一件事」。**我覺得這才是本質。

關於公司內部的資安訓練與開發體制怎麼調整,WARP的思路或許可以當參考。若要針對具體情況討論,歡迎從這裡與我們聯絡。


Footnotes

  1. Koi Security 對GlassWorm的偵測報告(2025年10月18日偵測、同日公布)。以VS Code擴充功能為對象,該報告的IOC一節列出16個遭植入的擴充功能(OpenVSX 15個、VS Code 1個),總下載次數為35,800次。竊取對象為npm認證token、GitHub驗證資訊、OpenVSX驗證資訊、Git驗證資訊,以及49種加密資產錢包擴充功能。會在感染裝置上安裝SOCKS proxy與隱藏的VNC伺服器。指揮系統以把Base64編碼的payload URL嵌入Solana區塊鏈交易備註為主系統,並以直接連到攻擊者伺服器、以及編碼進Google日曆活動標題的方式作為備援。具有用偷來的驗證資訊再去侵害其他套件與擴充功能的自我擴散循環。https://www.koi.ai/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace / 本文不記載具體的錢包位址、IP位址、URL等IOC,以避免遭到濫用。 2 3 4 5 6 7

  2. GlassWorm被認為是以VS Code擴充功能為對象、首次被確認的自我擴散型蠕蟲。https://www.veracode.com/blog/glassworm-vs-code-extension/https://www.bleepingcomputer.com/news/security/self-spreading-glassworm-malware-hits-openvsx-vs-code-registries/

  3. 用到的隱形字元是異體字選取器(Variation Selector),範圍為VS1到VS16對應U+FE00到U+FE0F(16個字元),VS17到VS256對應U+E0100到U+E01EF(240個字元)。GlassWorm的實作主要使用後者,支援對應0到255位元組值的256種值。異體字選取器具有為同一字元選取不同視覺表現的功能,因此本身不會被繪製,在多數文字編輯器裡視覺上不會出現。執行方式是從碼位還原位元組值,重組為Base64字串,解碼產生JavaScript原始碼,再經由 eval() 執行。https://www.endorlabs.com/reports/invisible-threats-glassworm-unicode-vscode 2 3

  4. 對策的具體作法。不單靠目視的程式碼審查、在送出PR前用 npx anti-trojan-source src/index.js 做本機檢查、在GitHub Actions用 npx anti-trojan-source --files='**/*.{js,ts,jsx,tsx}' --json 於合併前自動檢查並在偵測到時擋下、作為ESLint外掛納入既有工作流程的選項、定期輪替npm、GitHub、OpenVSX的token並刪除用不到的驗證資訊,以及持續確認第三方元件的可信度,均出自同一篇文章。https://snyk.io/articles/defending-against-glassworm/ 2 3 4

  5. Trojan Source。2021年由劍橋大學的Nicholas Boucher與Ross Anderson公布的攻擊手法,濫用Unicode的雙向文字控制字元,讓原始碼在顯示上的樣子與實際執行內容變成兩回事。攻擊者能用Unicode控制字元,在編碼層把token的排列順序對調,讓編譯器與人的審查者看到不同的邏輯。C、C++、C#、JavaScript、Java、Rust、Go、Python等主要語言的編譯器都受到影響,被指派CVE-2021-42574與CVE-2021-42694。https://access.redhat.com/security/vulnerabilities/RHSB-2021-007https://thehackernews.com/2021/11/new-trojan-source-technique-lets.htmlhttps://krebsonsecurity.com/2021/11/trojan-source-bug-threatens-the-security-of-all-code/ 2

本文在製作過程中使用了AI,並於發布前由人工查核一手資料並完成編輯。

貴公司對AI的理解到哪裡?

5分鐘的免費檢測,涵蓋從AI理解到資安意識共7個面向。

如果這篇文章對您有幫助,歡迎分享

分享

訂閱電子報

每週為您送上 AI 應用與出口管制的最新資訊

您登錄的電子郵件地址僅用於電子報寄送。

AIセキュリティを、現場で使える力にする

WARP SECURITYは、OWASP・NIST・ISO 42001・経産省ガイドラインに準拠した2日間の集中講座です。経営層と現場で分けて受講できます。

相關文章