ハクソク

世界を動かす技術を、日本語で。

グラスワームが帰ってきた:見えないUnicode攻撃の新たな波がリポジトリを襲う

概要

  • Glassworm による不可視Unicode攻撃が再び活発化
  • GitHub、npm、VS Codeなど複数エコシステムに被害拡大
  • 攻撃は不可視Unicode文字を使いマルウェアを隠蔽
  • 有名リポジトリも複数被害、AIを用いたカモフラージュも観測
  • Aikidoなどの専用検出ツールによる防御が重要

Glassworm攻撃の再来と拡大

  • 2025年から追跡しているGlasswormによる不可視Unicode攻撃の再発
  • 2026年3月にGitHub、npm、VS Code Marketplaceで大規模な攻撃キャンペーンを確認
  • PolinRiderキャンペーンとは別に、Glasswormが独自に活動再燃
  • 影響範囲は数百のGitHubリポジトリ、npmパッケージ、VS Code拡張機能に及ぶ

攻撃手法の概要

  • 攻撃者は不可視Unicode文字(PUAなど)を空文字列内に埋め込み、マルウェアペイロードを隠蔽
  • 例:const s = v => [...v].map(w => ...); eval(Buffer.from(s(``)).toString('utf-8'));
    • 一見空のバッククォート内に不可視文字を挿入
    • デコーダ関数で復元し、eval()で実行
  • 復元後のペイロードはSolana経由で第二段階スクリプトを取得し、トークンや認証情報を窃取

2026年3月の被害規模

  • GitHub上で少なくとも151件のリポジトリに同一パターンのデコーダを確認
    • 実際の被害数は削除済みリポジトリも含めさらに多い可能性
    • 攻撃期間は2026年3月3日~9日
  • npmやVS Code Marketplaceにも同様の手法で感染拡大
    • 例:@aifabrix/miso-client (npm), quartz.quartz-markdown-editor (VS Code)
  • 有名プロジェクトへの被害
    • pedronauck/reworm(1,460スター)
    • anomalyco/opencode-bench、doczjs/docz-plugin-css など

AIによるカモフラージュ

  • 攻撃コミットはドキュメント修正やバージョンアップ、リファクタなど自然な内容で偽装
  • 151件以上のリポジトリに対し個別最適化された変更が行われているため、大規模言語モデル(LLM)による自動生成の可能性が高い
  • 手動でこれほど多くの自然なコミットを用意するのは現実的ではない

検出と防御策

  • 肉眼や一般的なLintツールでは不可視Unicodeは検出困難
  • Aikidoなどのセキュリティツールは不可視Unicode混入を自動検出可能
    • Aikido利用者には100/100のクリティカル警告として通知
  • Aikido Safe Chainはnpm、yarn、pnpmなど主要パッケージ管理ツールに対応したリアルタイムマルウェア防御ツール
    • AIと人間の研究者による最新サプライチェーン攻撃の即時検出・遮断
  • 無料プランでもマルウェア検出機能を利用可能

まとめ

  • Glasswormの不可視Unicode攻撃は多エコシステム・AI活用・大規模化が特徴
  • 見えない脅威には専用検出ツールの導入が不可欠
  • オープンソース利用者はAikidoなどの対策ツールで早期検知・感染防止が重要

Hackerたちの意見

昨日ちょっとした議論があったね(9+9ポイント、9+4コメント) https://news.ycombinator.com/item?id=47374479 https://news.ycombinator.com/item?id=47385244
`eval` だけでも十分に警告サインだよね。
いや、違うよ。
そうだね、明らかにエクスプロイトがある例じゃないのを見てみたかったな。レビュアーが実際に見逃す可能性があるようなやつ。
JSの人じゃないけど、その行をそのまま受け取ると何もならないんじゃない?もし俺の理解が正しければ、マージされることはないはず。なんでノーオプをマージするの?
個人的には、「特定の攻撃に対してリポジトリの運営者自身が守る責任がある」と言うのはハードルが高いけど、これは該当すると思う。GitHubがSecret Scanningを提供しているのと同じように、言語的に標準的でない使い方をされているゼロ幅文字のスパンに対して警告を出すべきだよ。これにはLLMは必要なくて、n-タプルだけで十分。もちろん、OPのようなサードパーティのサービスがスキャンするボットを提供することもできるけど、もし脅威アクターがPRを提出できるエコシステムを作るなら、コミュニティへのコミットメントの一部として、目に見えない攻撃を可視化することを提供し、それを例外ではなく標準にするべきだと思う。[0] https://docs.github.com/en/get-started/learning-about-github...
GitHubの責任がどうかという難しい問題は置いといて、彼らが早急にやるべきことだと思う。
「特定のパターンに一致するファイルのために可視ASCIIを強制する」モードは、シンプルで役立つと思うよ。(これには.gitattributesファイルの「encoding」コマンドを使えるかもしれないけど、エラーや警告が報告されるかはわからないし、実装によるかもしれないね。)
その問題で指摘されているコードを、何をするのかも知らずにマージするメンテナーがいるなんて信じられない。目に見えない文字が見えるかどうかに関係なくね。ここには変換関数とeval()の呼び出しがある。ソフトウェアのメンテナーが何をするかも知らずにコードをマージするって、ソフトウェアのひどい状態を物語ってるよ。
もっとアップボートできたらいいのに。
今回の件でマージされたPRは6年前のもので、はっきりしてるね。https://github.com/pedronauck/reworm/pull/28 俺には、6年後に行われた強制プッシュが、今の履歴にあるコミットを上書きしたように見える。
> どんなメンテナーが、問題にハイライトされたようなコードを、何をするのかも知らずにマージするのか理解できない。ここで議論されている特定のケースに関係があるかは分からないけど、もしその脆弱性が以前信頼されていた提出者のアカウントにアクセスすることから来ているなら(または彼らを偽装できる場合)、PRをレビューするのが山ほどあるチームが、信頼できるソースからの更新を通してしまう可能性がある。これは怠慢や手抜きが原因だと正しく主張できるけど、ボランティアの労働力で運営されているプロジェクトは限られた時間しかないから、理解できる部分もあるよね。
リポジトリのオーナーが悪いコミットを強制プッシュして既存のものを置き換えたみたいだね。でも、なんで既存のタイムスタンプや著者を維持するために、例えば `git commit --amend -C df8c18` で改ざんしなかったんだろう?無害なPRだけど、「pedronauckが先週このプルリクエストに言及したコミットをプッシュした」っていうラインには注意してね:https://github.com/pedronauck/reworm/pull/28 元のコミット:https://github.com/pedronauck/reworm/commit/df8c18 修正されたコミット:https://github.com/pedronauck/reworm/commit/d50cd8 どちらにしても、オーナーのクレデンシャル(おそらくはマシン全体)が侵害されている明確なサインだね。
この技術の価値は、大きなペイロードをちょっとだけ隠すことができるところかな。見える部分は最悪だけど(魔法の数字やevalがいっぱい)、でも9000文字の16進数の行よりは見逃しやすいと思う(もしまだエンコードされてたり、デコードされてても暗号化されてたりするなら)。それに、Solanaやロシアのタイムゾーンについての記述があったりするし(好奇心でペイロードをデコードして解読したけど)。でも、結局は後から注入される必要があるよね。表面的なコードレビューでも見つかるはずだよ。
Unicodeは可視文字のためのものであるべきだよ。目に見えない文字は忌まわしい。カーソルを後ろに戻すためにUnicodeのいわゆる「文字」を使ってテキストを隠す方法も同様に。印刷物で消えるものはUnicodeに含まれるべきじゃない。Unicodeから取り除くべきだよ。
目に見える文字が正しく印刷されるために、目に見えない文字が存在するんだよね…
いいアイデアだね、スペースなんて誰が必要なの?
またまたダメなUnicodeのアイデアだね。同じグリフを持つ複数のコードポイントがあるのは。基本的なルールとして、印刷したときに見た目が同じ二つのUnicodeシーケンスは、同じコードポイントで構成されるべきだよ。
Unicodeは「デジタル化できる全ての世界の書記体系でのテキスト使用をサポートするように設計されている」んだ。Unicodeにはタブ、スペース、フォームフィード、キャリッジリターンが必要なんだよ。UnicodeはU+200E(左から右へのマーク)とU+200F(右から左へのマーク)が必要で、左から右、右から左の言語を切り替えるために使う。UnicodeはU+115F(ハングル初声フィラー)とU+1160(ハングル中声フィラー)が必要で、韓国語をタイプセットするために使う。UnicodeはU+200C(ゼロ幅非連結文字)が必要で、二つの文字が連結されないようにするために使う。UnicodeはU+200B(ゼロ幅スペース)が必要で、目に見えるスペースを挿入せずに単語の区切りの機会を示すために使う。Unicodeはモンゴル語の伝統的なアルファベットをエンコードするためにモンゴル語のフリー変種セレクターが必要なんだ。
>Unicodeからそれを削除しろ。これが実行可能な解決策だと思ってるの?
じゃあ、前の標準の複雑さのせいで新しい標準の問題が必要なの? Unicodeはすでに新しいスペース、CR、改行のような制御文字を持つASCIIのスーパーセットであるべきじゃないの? xD
Unicodeからスペースとタブを取り除くってこと?
その船は出てしまったけど、Unicodeは良いものだと思ってる。ただ、すべての領域でUnicodeをサポートするのは問題があると思う。テキスト内でÜを呪われたスマイリーとして使えるべきだし、Unicodeがサポートする多くの書き方は面白いことをもっと表現できる。それはいいことだよ。一方で、技術的なファイル名(GUIユーザー向け)と表示名が分かれていれば、ファイル名やコードベースでクレイジーな文字が必要な場面はかなり限られてる。技術者が使う実際のファイル名には、低ASCIIで十分だね。
ASCIIに見えない文字があることを考えると、これに関しては頑張ってほしいね。また、この攻撃は見えない文字を使ってるわけじゃなく、意味が割り当てられていない文字を使ってるみたいだね。
ターミナルエミュレーター(やテキストエディタなど)では非Unicodeモードを使ってるし、非Unicodeロケールも使ってる。ソースコードファイルの大半はASCIIで書くようにしてる(主にCだけど、場合によってはPC文字セットみたいな他の文字セットも使うことがあるけど、基本はASCIIだね)。こうすることで、自分のソフトウェアをメンテナンスする時に色々と楽になるよ。どうやら俺だけじゃないみたいで、他にも似たようなことを言ってる人を見たことがある。もし非ASCIIテキスト(例えばドキュメント用)が必要なら、別のファイルに保存した方がいいかも。少数の文字列リテラルにしか必要ないなら、\xエスケープを使うのもありだね。必要ならコメントを追加して説明するといいよ。この記事はJavaScriptについてだけど、他のプログラミング言語にも当てはまるよ。ただ、JavaScriptでも非ASCII文字の代わりに\uエスケープを使えるからね。(Cの代わりにもっと良いプログラミング言語をデザインする時のアイデアの一つは、非ASCIIバイトを許可したい場合はディレクティブやスイッチで指定しない限り、可視のASCII(といくつかの制御文字、使い方に制限あり)を強制することだよ。)
> ... ほとんどのソースコードファイルにはASCIIを使うよね。俺もそうしてる。ソースファイルはASCIIのサブセットだけになるようにスクリプトやフックを使って強制してるし、ASCIIコードの全てがソースコードに必要なわけじゃない。リソースファイルにはUnicode文字列が全然問題ないし、ソースファイルでUnicode文字を一切使わずにi18n/l10nアプリやウェブアプリを作ることもできる。もし本当に必要なら、多くの言語でASCIIエスケープが使えるしね。中には「Author: ...」のコメントがASCIIでちゃんと書けないって文句を言う人もいるけど、冗談を言うなら、近いうちにこうなるだろうね:# Author: Claude Opus 27.2 だから、結局どうでもいい話だよ。
CP437万歳!今、ソースリポジトリでのUnicodeの最大の使い道はLLMのゴミかもしれないから、全然その欠如を寂しく思わないよ。
こういうことの脅威は本当に過大評価されてる気がする。確かにペイロードは見えないけど(正直言うと、見えないのに驚いてる。PUA文字は通常、俺にはボックスと16進コードで表示される)、空の文字列をevalに通す部分は見えるよね。もしeval()で空の文字列を使ってるのに気づかないほどコードをレビューしてないなら、非難されないペイロードにも気づかないんじゃない?
脅威は、このライブラリに依存しているか、VS Codeの拡張機能を使っていることだね。
コードレビューでこれがどれだけ見えないかが怖い。Unicodeの方向性オーバーライドやゼロ幅文字は、ほとんどのエディタではデフォルトで表示されない。これを確実にキャッチする信頼できるプレコミットフックの設定知ってる人いる?
GitHubはUnicode文字について警告してるって宣伝してるけど、実際には機能してないよね。これをバグバウンティに報告したら、報酬をもらったけど「修正しません」って言われた。https://joshua.hu/2025-bug-bounty-stories-fail#githubs-utf-f... 正確な引用は「提出ありがとう!あなたの報告をレビューし、発見を確認しました。脆弱性を成功裏に悪用する難易度、潜在的なデータや情報の露出、影響を受けるシステムやユーザーなどの要素を考慮した結果、我々の報酬構造に適用される重大なセキュリティリスクではないと判断しました。」って感じ。面白いのは、実際に$500と生涯GitHub Proをもらったことだね。