1万件のGitHubリポジトリがマルウェアを配布していた:プラットフォーム信頼の逆説

GitHubは開発者にとって安全な場所なのか、それとも「信頼」という名のもとに包まれた攻撃ベクターなのか。

はじめに

オープンソースエコシステムにおけるGitHubの地位は、単なるコードホスティングサービスを超えている。開発者は見知らぬリポジトリのコードをダウンロードする際にも、「GitHubにあるなら多少は大丈夫だろう」という暗黙の信頼を抱きがちだ。その信頼はプラットフォームが数十年をかけて蓄積してきた評判に基づいており、同時に最も危険な脆弱性にもなり得る。

2026年6月、あるセキュリティ研究者が自身のリポジトリが大規模に複製されていることに気づいた。最初は通常のフォークのように見えたが、詳しく調べるとパターンが異なっていた。検索結果に現れたクローンリポジトリは公式リリースのように見えるzipアーカイブを提供しており、その中にはLuaJITベースのトロイの木馬が潜んでいた。研究者が範囲を広げて分析した結果はさらに衝撃的だった。GitHub全体で同一のパターンで運営されているリポジトリが実に1万件にも上ることが判明したのだ。頻繁に更新される4万件のリポジトリのうち、25%がマルウェア配布に利用されていた。

この事件は単純なマルウェア拡散事例ではない。開発者という特定集団を精密に狙い、GitHubという信頼インフラを武器化し、プラットフォームの対応メカニズムがいかに脆弱であるかを赤裸々に示した。GitHubはこの事実を把握した後も自動化された検出システムを稼働させず、通報されたリポジトリだけを2週間後に削除した。その間も新たなリポジトリが次々と生まれ続けた。

攻撃の解剖:コミット操作と検出回避の精巧な設計

このキャンペーンの技術的な精巧さは複数の層で確認できる。攻撃者たちはGitHubの検出アルゴリズムとセキュリティツールの盲点を正確に把握し、その隙間を突いた。

コミット履歴の継続的な上書き

最も顕著な特徴はコミットパターンだ。各リポジトリは1日に1〜24回、README.mdを更新するコミットを生成する。しかし各コミットは直前のコミットを削除する。つまりリポジトリのgit履歴には常に最新のコミット1件だけが残る。この手法は二つの目的を同時に達成する。第一に、git履歴を分析して異常活動を検出するツールを無力化する。過去のコミットが存在しないため、比較対象そのものが消えてしまう。第二に、GitHubの最近の活動ベースの露出アルゴリズムを逆手に取る。頻繁なコミットはリポジトリを「活発にメンテナンスされているプロジェクト」のように見せ、検索結果での視認性を高める。

すべてのコミットメッセージは「Update README.md」に統一されている。これは意図的な選択と考えられる。GitHubの内部的な異常検出システムがコミットメッセージを解析するとすれば、「Update README.md」は極めて正常なメッセージであるため、フィルタを通過する可能性が高い。

偽のコントリビューターと合法性の演出

リポジトリには複数の偽コントリビューターアカウントが追加されている。GitHubでリポジトリを見る際、コントリビューターリストは信頼性を示す主要なシグナルの一つだ。「複数の人が協力して作ったプロジェクト」という印象は、単独アカウントが運営するリポジトリよりも正当に見える。攻撃者たちはこの心理を利用した。

また、これらのリポジトリはGitHubのフォーク判定ロジックをかわしながら、クローンされたコンテンツを含んでいる。フォークに分類されると元のリポジトリとの関係が明示され、疑念を招く可能性がある。独立したリポジトリのように見せながら、合法的なオープンソースプロジェクトを装う戦略だ。

VirusTotal回避の巧妙さ

悪意あるファイルの配布方法も巧みだ。研究者がzipアーカイブをVirusTotalにアップロードしたとき、検出結果はゼロだった。しかしアーカイブ内のファイルを直接スキャンすると、マルウェアであることが確認された。この差は単なる偶然ではない。

zipアーカイブとしてパッケージ化することで、ほとんどの自動化されたセキュリティスキャンツールは内部を深く調べないか、調べても既知のハッシュとの比較に失敗する。アーカイブ自体は既知の悪意あるハッシュと一致しないため、クリーンと判定される。GitHubからzipファイルを直接配布する手法は、この回避技術を完璧に活用している。ユーザーが「リリースファイル」をダウンロードする行為は自然なワークフローの一部であるため、疑惑を招きにくく、かつセキュリティツールの検査範囲外に置かれることにもなる。

悪意あるアーカイブの構成

ダウンロードされたzipアーカイブの内部には四つのファイルが含まれている。Application.cmdというコマンドスクリプトが実行エントリーポイントとして機能し、実行ファイル、データファイル、DLLライブラリが同梱されている。この構成は正規のソフトウェアインストールパッケージと外観上の区別が難しい。ユーザーがオープンソースツールをインストールしようとApplication.cmdを実行した瞬間、LuaJITトロイの木馬がシステムに侵入する。

標的の精密さ:マイナーな検索ワードの狙い撃ち

攻撃者たちはGitHubで人気のリポジトリをクローンしなかった。代わりに、新たに作成されたリポジトリを複製した。この選択は戦略的に正確だ。人気リポジトリをクローンすれば、オリジナルとの比較が容易になり、オリジナルのコミュニティによって素早く通報される可能性が高い。一方、新しく作成された、あまり知られていないリポジトリをクローンすれば比較対象がなく検出が難しい。同時に、「特定の機能を持つツール」を検索するユーザーに上位結果として表示される可能性がある。具体的な技術用語や複合語で検索する開発者ほど、この罠に引っかかりやすい。

一部のリポジトリは12ヶ月以上アクティブ状態を維持しながら検出されなかった。1年以上にわたってマルウェアを配布するリポジトリがGitHub上に存在できたという事実は、この攻撃が単発の実験ではなく、体系的に運営された長期キャンペーンであったことを示している。

GitHubの対応失敗:通報依存モデルが露わにしたプラットフォーム責任の空白

研究者が発見をGitHubに報告したとき、プラットフォームの対応は期待を大きく下回った。GitHubは通報されたリポジトリを削除するのに約2週間を要し、それも明示的に通報されたリポジトリだけを削除した。研究者が確認した1万件のリポジトリ全体を自動的に検出・削除する措置は講じられなかった。削除されたリポジトリの跡にはすぐに新しいリポジトリが生まれた。

5億件のリポジトリと自動検出の不在

GitHubには現在5億件を超えるリポジトリが存在する。この規模では手動レビューは現実的に不可能だ。それにもかかわらず、GitHubはこのキャンペーンで見られたパターン——1日に数十回のコミット、単一コミット履歴、一律の「Update README.md」メッセージ、偽コントリビューター、zipアーカイブを通じたバイナリ配布——を自動検出するシステムを運用していない。

これは技術的に不可能な問題ではない。これらのパターンは十分に構造化されており、ルールベースの検出システムでもかなりの部分を絞り込むことができる。1日に20回以上READMEだけを修正するリポジトリ、git履歴を継続的に上書きするリポジトリ、特定期間内に大量のzipアーカイブを公開する新規アカウント。これらのシグナルを組み合わせれば、疑わしいリポジトリを絞り込むことは不可能ではない。

通報依存モデルの構造的限界

GitHubの現行対応体制はコミュニティからの通報に依存している。このモデルには根本的な非対称性が存在する。攻撃者は自動化されたスクリプトでリポジトリを大量に作成・管理できるが、被害者である開発者や研究者は個別にリポジトリを発見し、手動で通報しなければならない。攻撃の速度と通報の速度が構造的に不均衡なのだ。

さらに深刻な問題は通報の成功率の低さだ。実際にマルウェアをダウンロードした開発者のうちGitHubに通報する割合は極めて低い。ほとんどは感染の事実自体に気づかないか、気づいてもどこに通報すべきかわからないか、通報しても効果がないと判断する。このキャンペーンが12ヶ月以上継続できた理由の一つも、この通報の空白にある。

日本のOSSコミュニティにおける類似事例

このパターンは日本の開発者コミュニティにとっても他人事ではない。2023年には日本語のQiita記事やZenn記事を模倣したnpmパッケージが複数発見され、日本語圏の開発者を特定の標的にした可能性が指摘された。また、日本のCERT(JPCERT/CC)は2024年のレポートで、OSS依存ライブラリを経由したサプライチェーン攻撃が国内でも急増していることを警告している。GitHub上のリポジトリを直接信頼してzipをダウンロードする行為は、日本でも広く見られる開発慣行だ。この習慣が攻撃者にとって「的が大きい」理由となっている。

プラットフォーム責任論の台頭

GitHubの対応は、プラットフォーム責任に関する根本的な問いを提起する。このキャンペーンのパターンは十分に検出可能だった。研究者一人が把握できたことをプラットフォームが把握できなかったのは、能力の問題ではなく意志とリソース配分の問題だ。

もちろん、すべてのコンテンツを事前に検閲することはオープンプラットフォームの性格と相反する。しかし、明確な悪意あるパターンに対する自動化された事後検出と迅速な削除は別の問題だ。メールサービスプロバイダーがスパムやフィッシングメールを自動的にフィルタリングするように、GitHubも明白な悪意あるリポジトリパターンを検出し、自動的に隔離するシステムを構築できるはずだし、構築すべきだ。

MicrosoftがGitHubを買収して以降、セキュリティへの投資が増加したことは事実だ。しかしこの事件は、その投資がいまだプラットフォームレベルのマルウェアキャンペーン検出には到達していないことを示している。

開発者セキュリティの新たな現実:サプライチェーン攻撃とオープンソース信頼の再定義

この事件がセキュリティコミュニティで注目される理由は被害規模だけではない。攻撃の標的が一般ユーザーではなく開発者であったこと、そして開発者の信頼モデルを精密に狙ったことが核心だ。

開発者が狙われる理由

開発者は一般ユーザーよりもはるかに価値の高い標的だ。開発者のシステムにはソースコード、クラウドサービスの認証情報、APIキー、データベースアクセス権限が存在する。開発者のシステムを掌握すれば、単純な個人被害を超えて、その開発者が管理するサービスと顧客データ全体へと攻撃範囲が拡大しうる。CI/CDパイプラインに侵入すれば、デプロイされるソフトウェア自体が汚染される。

これがソフトウェアサプライチェーン攻撃だ。開発者を感染させることは、その開発者が作るソフトウェアのすべてのユーザーを潜在的な被害者にすることと同義だ。

オープンソース信頼モデルの脆弱性

オープンソース文化にはコードを公開・共有するという根本的な信頼が内在している。「ソースを見られるから安全だ」という認識は部分的には正しいが、このキャンペーンはその信頼の盲点を突く。開発者たちはコードのソースを確認する代わりに、プラットフォームの信頼性に依存する傾向がある。GitHubにあるという事実だけで、信頼の基準線が形成されてしまう。

実践的な対応策として以下が挙げられる。第一に、GitHub検索で見つけたリポジトリのzipアーカイブを実行する前に、必ずソースコードを直接確認する。第二に、リポジトリのgit履歴が異常に短い、または単一コミットしか存在しない場合は疑う。第三に、公式配布チャンネル(パッケージマネージャーなど)を通じて検証済みのソフトウェアのみを使用する。第四に、見知らぬzipアーカイブを実行する際は隔離された環境を使用する。

今後の展望:パターンの進化

このキャンペーンが露見した後、同一のパターンがそのまま維持される可能性は低い。攻撃者たちはすでに検出を避けるために戦術を変更しているだろう。コミットパターンを不規則にしたり、より多様なコミットメッセージを使用したり、偽のIssueやプルリクエストを追加して合法性を強化する方向に進化しうる。GitHub npmパッケージレジストリやGitHub Actionsマーケットプレイスを通じた類似攻撃もすでに報告されているため、攻撃面はリポジトリ検索だけにとどまらない。

日本のエンジニアリングコミュニティに特有のリスクとして、技術ブログやQiitaの記事で紹介されたツールへの信頼が高いことが挙げられる。「記事で紹介されていた」「Twitterでバズった」という社会的証明が加わると、開発者の警戒心はさらに下がる。このような文脈でGitHubリポジトリへの誘導が行われた場合、被害が拡大するリスクがある。

まとめ

1万件の悪意あるリポジトリキャンペーンは、いくつかの不都合な真実を再確認させる。プラットフォームへの信頼は、セキュリティの証明ではない。GitHubにあるという事実がソフトウェアの安全性を保証しない。オープンソースエコシステムの開放性はそれ自体が強みだが、その開放性を悪用する精巧なキャンペーンが存在するという現実も受け入れなければならない。

プラットフォーム側の観点では、GitHubの対応は不十分だった。通報依存モデルは、規模化された自動化攻撃の前では十分ではない。5億件のリポジトリを抱えるプラットフォームであれば、明確な悪意あるパターンを検出する自動化システムを構築することは、選択ではなく義務だ。

開発者個人の観点では、「どこから来たか」より「何であるか」を中心に評価する習慣が求められる。コードの出所よりコード自体を確認し、バイナリ実行前に隔離環境を使用し、公式パッケージチャンネルを優先する原則は、サプライチェーン攻撃の波を低減する最も実践的な防御だ。

信頼を構築するには数十年かかり、崩壊するには一度の感染で十分である。


出典