あなたのコードレビュー画面に表示されている1行のJavaScript。見た目はただのバッククォート2つに挟まれた空文字列。しかし実際には、その「空」の中に大量の不可視マルウェアが隠れている。
2026年3月、ベルギーのAikido SecurityやStepSecurity、OpenSourceMalwareコミュニティが相次いで警告を発した。「GlassWorm」と名付けられたサプライチェーン攻撃は、Unicodeの不可視制御文字を悪用し、GitHub・npm・VS Code拡張の433件以上を汚染していた。
攻撃の核心は、Unicodeの異体字セレクター(Variation Selector)だ。本来は漢字やアラビア文字の字形を指定するための制御文字で、以下の2つの範囲が悪用されている。
| Unicode範囲 | 名称 | 本来の用途 | 攻撃での役割 |
|---|---|---|---|
U+FE00〜U+FE0F |
Variation Selectors | 絵文字・漢字の字形指定 | 0〜15の値をエンコード |
U+E0100〜U+E01EF |
Variation Selectors Supplement | 拡張字形指定 | 16〜239の値をエンコード |
これらの文字は表示幅がゼロで、GitHub・VS Code・ターミナル・diffビューアのすべてで完全に不可視。テキストエディタのカーソルすら止まらない。
攻撃コードは以下のようなデコーダー関数を使い、不可視文字列からバイト列を復元する。
// GlassWormデコーダーパターン(検出用に簡略化)
const decode = v => [...v].map(w => (
w = w.codePointAt(0),
w >= 0xFE00 && w <= 0xFE0F ? w - 0xFE00 :
w >= 0xE0100 && w <= 0xE01EF ? w - 0xE0100 + 16 : null
)).filter(n => n !== null);
// 見た目は空文字列だが、数千の不可視文字が含まれている
eval(Buffer.from(decode(``)).toString('utf-8'));
バッククォートの間に不可視文字が大量に埋め込まれ、eval()で実行される。見た目は1行の空文字列だが、不可視文字として大量のマルウェアコードが隠されている。
従来のマルウェアはC2(Command & Control)サーバーにドメインやIPアドレスを使うため、セキュリティチームがドメインを差し押さえれば無力化できた。GlassWormはSolanaブロックチェーンのウォレットをC2として使う。
2025年11月27日から2026年3月13日までの間に、研究者は50回のトランザクションを確認。攻撃者はウォレットのメモフィールドを更新するだけで、マルウェアの接続先を自在に変更できる。
GlassWormは単一のプラットフォームに留まらず、開発エコシステム全体に拡散した。
| プラットフォーム | 汚染数 | 手法 |
|---|---|---|
| GitHub(Pythonリポジトリ) | 数百件 | 盗んだトークンでforce-push |
| GitHub(JS/TSリポジトリ) | 151件 | 不可視Unicodeペイロード |
| VS Code / Open VSX拡張 | 72件 | 悪意ある拡張機能 |
| npmパッケージ | 10件 | 汚染パッケージ |
| 合計 | 433件以上 | — |
影響を受けたプロジェクトには、状態管理ライブラリ「reworm」(1,460スター)、Wasmerの公式サンプルリポジトリ「wasmer-examples」、OpenCode関連の「opencode-bench」などが含まれる。悪意あるVS Code拡張7つの合計ダウンロード数は約35,800回に達していた。
攻撃者はまずVS Code拡張やnpmパッケージから開発者のGitHubトークンを盗み、そのトークンで正規リポジトリにforce-pushする。コミットは「ドキュメント修正」「バージョンアップ」などに偽装され、LLMで生成された自然なコミットメッセージが使われている可能性がある。
| 時期 | 出来事 |
|---|---|
| 2025年3月 | Aikido Securityが不可視Unicode使用のnpmパッケージを最初に発見 |
| 2025年5月 | Unicodeベースの攻撃リスクに関する研究論文が公開 |
| 2025年10月17日 | Koi SecurityがOpen VSXの汚染拡張を特定 |
| 2025年11月27日 | Solana C2のトランザクション開始 |
| 2026年1月31日 | 追加の悪意あるOpen VSX拡張が発見 |
| 2026年3月3〜9日 | 大規模波:1週間で151以上のGitHubリポジトリが汚染 |
| 2026年3月13日 | 最後に確認されたC2トランザクション更新 |
| 2026年3月16日 | Aikido Security等が詳細レポートを公開 |
| 2026年4月3日 | 複数のセキュリティブログが詳細分析を公開 |
マルウェアが狙うのは開発者の資産だ。
コード分析から、マルウェアはロシア語ロケールが検出された場合に実行をスキップする仕様が確認されている。ロシア語圏の攻撃者が関与している可能性を示唆するが、偽旗工作の可能性もあり、確定的な帰属は困難だ。
以下のコマンドで感染の兆候をチェックできる。
# 1. GlassWorm特有の変数名を検索
grep -r "lzcdrtfxyqiplpd" --include="*.js" --include="*.ts" .
# 2. 不可視Unicode文字(異体字セレクター範囲)のスキャン
grep -rP '[\x{FE00}-\x{FE0F}]|[\x{E0100}-\x{E01EF}]' --include="*.js" .
# 3. 感染時に作成されるファイルの確認
ls -la ~/init.json ~/node-v22* 2>/dev/null && echo "⚠️ 感染の痕跡あり"
# 4. バッククォート内の不可視文字を検出(Node.js)
node -e "
const fs = require('fs');
const code = fs.readFileSync(process.argv[1], 'utf-8');
const invisible = code.match(/[\uFE00-\uFE0F\u{E0100}-\u{E01EF}]/gu);
if (invisible) console.log('⚠️ 不可視文字検出:', invisible.length, '個');
else console.log('✓ 不可視文字なし');
" target_file.js
| 対策 | 優先度 | 効果 |
|---|---|---|
| デフォルトブランチへのforce-push禁止 | 最優先 | 不正コミットの注入を防止 |
| ハードウェアキー(YubiKey等)認証 | 最優先 | トークン窃取後の悪用を防止 |
| Unicode制御文字の自動スキャン導入 | 高 | 不可視ペイロードの検出 |
| 依存関係のロック+ハッシュ検証 | 高 | サプライチェーン改ざん検出 |
| VS Code拡張の定期監査 | 中 | 悪意ある拡張の排除 |
Claude Codeのようなコーディングツールを使う場合、感染リポジトリのコードをAIが読み込むと人間のレビューなしにペイロードが実行されるリスクがある点にも注意が必要だ。
専門家が指摘するのは、LLMを使った攻撃の自動化だ。GlassWormでは以下の場面でAIが悪用された可能性がある。
Hacker Newsの議論では、「GitHubはUnicode警告機能を持っているが、バグバウンティ報告者に対して『修正予定なし』と回答した」という情報も共有されている。開発環境のセキュリティを個々の開発者だけに委ねるのは限界があり、プラットフォーム側の対応が問われている。
GlassWormは「サプライチェーン攻撃」の新たな段階を示している。コードの見た目だけを信頼する時代は終わった。
この記事はAI業界の最新動向を速報でお届けする「AI Heartland ニュース」です。