- PyPI
lightning2.6.2 と 2.6.3 が2026年4月30日に公開された後、サプライチェーン攻撃に悪用され、pip install lightningだけで隠された_runtimeディレクトリと難読化された JavaScript ペイロードが実行される可能性がある - 悪性ペイロードはモジュールのインポート時に自動実行され、認証情報、認証トークン、環境変数、クラウドシークレットを窃取し、GitHub リポジトリの汚染も試みる
- 今回の攻撃は侵入口が PyPI だが、ワームの拡散は npm を通じて行われ、npm 公開資格情報が見つかると、公開可能なパッケージに
setup.mjsドロッパーとrouter_runtime.jsを注入し、パッチバージョンを再公開する - データ流出には HTTPS POST、GitHub コミット検索のデッドドロップ、攻撃者管理の公開 GitHub リポジトリ、被害者リポジトリへの直接プッシュという 4つの並列チャネル が使われ、
EveryBoiWeBuildIsAWormyBoiコミット接頭辞と"A Mini Shai-Hulud has Appeared"リポジトリ説明が指標として残る - マルウェアは Claude Code の
.claude/settings.jsonにあるSessionStartフックと、VS Code の.vscode/tasks.jsonにあるrunOn: folderOpenタスクを埋め込み、リポジトリを開くたびにドロッパーを実行し、影響期間中に悪性パッケージをインポートしたマシンは完全に侵害されたものとして扱うべきである
影響を受けるパッケージと確認手順
lightningは、画像分類器の構築、LLM のファインチューニング、拡散モデルの実行、時系列予測器の開発チームの依存関係ツリーに頻繁に含まれるディープラーニングフレームワークである-
影響を受けるパッケージ
lightningバージョン2.6.2lightningバージョン2.6.3
-
Semgrep 顧客向け確認手順
- 最近プロジェクトスキャンを実行していない場合は、新しいスキャンを実行する必要がある
- advisories ページ で、プロジェクトが該当パッケージバージョンを最近インストールしたか確認できる
- dependency filter で一致項目を確認でき、「No matching dependencies」と表示される場合、そのプロジェクトでは悪性依存関係をアクティブには使用していないことを意味する
- 一致項目がある場合は、以下の侵害指標にある
.claude/と.vscode/ディレクトリ内の予期しないファイルをリポジトリで監査する必要がある - 影響を受けた環境に存在した可能性のある GitHub トークン、クラウド認証情報、API キーをローテーションする必要がある
- サプライチェーン攻撃への対応と待機期間に関する一般的な助言は $foo compromised in $packagemanager と Attackers are Still Coming for Security Companies で扱っている
PyPI から npm に拡散する構造
- mini Shai-Hulud が npm を直接狙っていたのとは異なり、今回の攻撃の侵入口は PyPI である
- 悪性ペイロードは依然として JavaScript であり、ワームの拡散は npm を通じて発生する
- 実行されたマルウェアが npm 公開資格情報を見つけると、そのトークンで公開可能なすべてのパッケージに
setup.mjsドロッパーとrouter_runtime.jsを注入する - その後、
scripts.preinstallをドロッパー実行に設定し、パッチバージョンを上げて再公開する - そのパッケージをインストールした下流の開発者は、自分のマシンで完全なマルウェアを実行することになり、トークン窃取とパッケージワーム感染が続く
データ流出方式
- 窃取機能は以前のキャンペーンの Mini Shai-Hulud のメカニズムと設計を共有しており、個別の経路が遮断されてもデータが流出するよう、4つの並列チャネルを使用する
- 攻撃には
EveryBoiWeBuildIsaWormBoiという公開リポジトリ作成など、Shai-Hulud テーマが含まれる - 攻撃指標の構造は以前の mini Shai-Hulud キャンペーンと一致しており、悪性コミットメッセージは
EveryBoiWeBuildIsAWormyBoi接頭辞を使って、元の Mini Shai-Hulud 攻撃と区別される -
HTTPS POST による C2 転送
- 窃取データはポート443経由で攻撃者管理サーバーへ即座に POST される
- ドメインとパスはペイロード内に暗号化された文字列として保存され、静的解析を困難にしている
-
GitHub コミット検索デッドドロップ
- マルウェアは GitHub コミット検索 API をポーリングし、
EveryBoiWeBuildIsAWormyBoi接頭辞付きのコミットメッセージを探す - コミットメッセージは
EveryBoiWeBuildIsAWormyBoi:<base64(base64(token))>形式の二重 Base64 エンコードされたトークンを運ぶ - デコードされたトークンは、その後の操作のための Octokit クライアント認証に使われる
- マルウェアは GitHub コミット検索 API をポーリングし、
-
攻撃者管理の公開 GitHub リポジトリ
- ランダムに選ばれた Dune の単語名と
"A Mini Shai-Hulud has Appeared"という説明を持つ新しい公開リポジトリが作成される - この説明は GitHub 上で直接検索できる
- 窃取された認証情報は
results/results-<timestamp>-<n>.jsonとしてコミットされ、API 経由では Base64 エンコードされるが内部は通常の JSON である - 30MB を超えるファイルは番号付きチャンクに分割される
- コミットメッセージは偽装のため
chore: update dependenciesを使用する
- ランダムに選ばれた Dune の単語名と
-
被害者リポジトリへの直接プッシュ
- マルウェアが
ghs_GitHub サーバートークンを取得すると、被害者のGITHUB_REPOSITORYの全ブランチに窃取データを直接プッシュする
- マルウェアが
窃取対象
- マルウェアはローカルファイル、環境、CI/CD パイプライン、クラウドプロバイダー全般の認証情報を狙う
-
ファイルシステム
- 80以上の認証情報ファイルパスをスキャンし、
ghp_、gho_、npm_トークンを探す - ファイルごとに最大 5MB まで処理する
- 80以上の認証情報ファイルパスをスキャンし、
-
シェルと環境変数
gh auth tokenを実行するprocess.envのすべての環境変数をダンプする
-
GitHub Actions
- Linux ランナー上で内蔵 Python を使い、
Runner.Workerプロセスメモリをダンプする "isSecret":trueとマークされたすべてのシークレットと、GITHUB_REPOSITORY、GITHUB_WORKFLOWを抽出する
- Linux ランナー上で内蔵 Python を使い、
-
GitHub 組織
- トークンスコープ
repo、workflowを確認する - GitHub Actions の組織シークレットを列挙する
- トークンスコープ
-
AWS
- 環境変数、
~/.aws/credentialsプロファイル、IMDSv2169.254.169.254、ECS169.254.170.2を試してsts:GetCallerIdentityを呼び出す - Secrets Manager のすべての値と SSM パラメータを列挙して取得する
- 環境変数、
-
Azure
DefaultAzureCredentialを使用してサブスクリプションを列挙し、Key Vault シークレットにアクセスする
-
GCP
GoogleAuthで認証する- Secret Manager のすべてのシークレットを列挙して取得する
- 対象範囲にはローカル開発環境、CI ランナー、主要3大クラウドプロバイダーのすべてが含まれる
- 影響を受けた期間に悪性パッケージをインポートしたすべてのマシンは、完全に侵害 されたものとして扱うべきである
開発ツールを通じた永続化の確保
- リポジトリ内部に入った後、マルウェアはよく使われる開発ツールである Claude Code と VS Code を狙って永続化フックを埋め込む
-
Claude Code
- マルウェアはリポジトリの Claude Code 設定ファイル
.claude/settings.jsonに、matcher: "*"のSessionStartフックを書き込む - フックは
node .vscode/setup.mjsを指す - 開発者が感染したリポジトリで Claude Code を開くたびに実行され、セッション開始以外のツール使用やユーザー操作は不要である
- マルウェアはリポジトリの Claude Code 設定ファイル
-
VS Code
- VS Code ユーザーを狙い、
.vscode/tasks.jsonにrunOn: folderOpenタスクを埋め込む - プロジェクトフォルダが開かれるたびに
node .claude/setup.mjsが実行される
- VS Code ユーザーを狙い、
-
ドロッパー
setup.mjs- どちらのフックも、自己完結型の Bun ランタイムブートストラッパーである
setup.mjsを呼び出す - Bun がインストールされていない場合、GitHub Releases から
bun-v1.3.13を静かにダウンロードする - Linux x64、Linux arm64、Linux musl、macOS x64、macOS arm64、Windows x64、Windows arm64 を処理する
- その後、完全な 14.8MB ペイロードである
.claude/router_runtime.jsを実行し、/tmpからクリーンアップする
- どちらのフックも、自己完結型の Bun ランタイムブートストラッパーである
-
悪性 GitHub Actions ワークフロー
- マルウェアが書き込み権限のある GitHub トークンを持っている場合、被害者リポジトリに
Formatterというワークフローをプッシュする - すべての push で
${{ toJSON(secrets) }}を通じてすべてのリポジトリシークレットをダンプする - 結果を
format-resultsというダウンロード可能な Actions アーティファクトとしてアップロードする - Actions は正常に見せるため、特定のコミット SHA に固定される
- CI で感染した
lightningパッケージを受け取り、書き込み権限トークンを持つリポジトリは、それらのファイルを監査する必要がある
- マルウェアが書き込み権限のある GitHub トークンを持っている場合、被害者リポジトリに
侵害指標
-
検索可能な指標
EveryBoiWeBuildIsAWormyBoi接頭辞付きのコミットメッセージはデッドドロップトークン運搬手段として使われ、GitHub コミット検索で見つけられる"A Mini Shai-Hulud has Appeared"という説明を持つ GitHub リポジトリは攻撃者の流出用リポジトリであり、直接検索可能である
-
パッケージ
lightning@2.6.2lightning@2.6.3
-
ファイルとシステムアーティファクト
_runtime/start.py: インポート時にペイロードを初期化する Python ローダー_runtime/router_runtime.js: 難読化された JavaScript ペイロードであり、14.8MB の Bun ランタイム_runtime/: 悪性パッケージバージョンに追加されたディレクトリ.claude/router_runtime.js: 被害者リポジトリに注入されたマルウェアのコピー.claude/settings.json: 被害者リポジトリに注入された Claude Code フック設定.claude/setup.mjs: 被害者リポジトリに注入されたドロッパー.vscode/tasks.json: 被害者リポジトリに注入された VS Code 自動実行タスク.vscode/setup.mjs: 被害者リポジトリに注入されたドロッパー
1件のコメント
Hacker Newsの反応
単なる頻度の錯覚かもしれないが、最近は主要パッケージで有名なサプライチェーン攻撃がかなり多く見られる
今のHNの最初の数ページを見ても、別々の事例を扱った投稿がいくつもある
10年前の
left-padを振り返ると、今は成功した攻撃が当時より増えているのではと思うし、おそらくその通りだろう成功した攻撃の価値も確実に大きくなっているはずだが、パッケージのリリース前に検知する能力が、コミュニティ全体として実際に向上しているのか気になる
商用ソフトウェア企業はもっとうまくやるべきだが、趣味・アマチュアのコードとして始まり、その後多くのプロジェクトの依存先になるようなケース向けの、汎用的で簡単なツールはまだ不足しているように見える
今のSAPサプライチェーン攻撃スレッドにも同じコメントを投稿した: https://news.ycombinator.com/item?id=47964003
以前は
npm installを手動で実行することがもっと多く、ビルドが壊れたときか、せいぜいたまに実行する程度だったはずだサプライチェーン攻撃は、人間が、より正確にはパイプラインが、新しいリリースが出るやいなや何も考えずにパッケージを自動更新することに依存している
これが良いビジネスモデルかは分からないし、たぶんそうではないだろう
left-padは攻撃ではなく、NPMのバグだったすでに公開されていて、別のパッケージが依存しているパッケージバージョンを削除できてはいけなかったし、逆に新しいバージョンで、まだ誰も依存していない特定のパッケージバージョンは削除できるべきだった
left-padの作者がサービスを離れる意図ですべてのデータを消そうとしたとき、NPMはエラーコードを返すべきだったWikipediaによると、Koçuluがnpm, Inc.の決定に失望し、プラットフォームの一部として残りたくないと述べた際、NPM作者のSchlueterが、彼が登録した273個のモジュールを削除するコマンドを提供したという
奇妙なのは、4件のセキュリティ問題が上がったのに、どれも
pl-ghostというボットが自動コメントを付けて閉じていたことだ [1][2][3][4]結局、このうち[4]だけがきちんと処理され、ボットのコメントはすべて削除された
別のレポート[5]ではそのボットコメントを見ることができ、元記事より多くの情報を与えている
[1] https://github.com/Lightning-AI/pytorch-lightning/issues/216...
[2] https://github.com/Lightning-AI/pytorch-lightning/issues/216...
[3] https://github.com/Lightning-AI/pytorch-lightning/issues/216...
[4] https://github.com/Lightning-AI/pytorch-lightning/issues/216...
[5] https://socket.dev/blog/lightning-pypi-package-compromised
攻撃者はこのアカウントで新しいActionsワークフローを作成し、実行されたワークフローからPyPIシークレットをパースして抜き取りました
パッケージをリリースした後は、そのアカウントでコメントを投稿し、こちらを少しあざ笑っていました
依存関係がまったくない日が早く来てほしい
極端な例として、最近は娘のためのインタラクティブな教育アプリを作るとき、Opusに純粋なJavaScriptとHTMLだけを使わせている
二重振り子から流体シミュレーションまで一発でうまく動き、昔なら依存関係が数百個あったはずだ
MITライセンスのコードなら、Opusに必要な部分だけを正確に抽出し、自分の用途向けに修正して組み込ませることもできる
趣味プロジェクトでは今のところうまくいっていて、今後は本番ソフトウェアでも依存関係がなくなってほしい
ChromeがあるAPIの形を変えたら自分で見つけて直す必要があるし、モロッコが夏時間の開始時期を変えたら日時処理コードも自分で更新しなければならない
こうしたことは、ライブラリが代わりに処理してくれるから当たり前だと思っていた部分だ
娘が来週には興味を失うような二重振り子シミュレータなら大したことではないが、今後無期限に動き続けるものを作る会社にとっては問題になる
MITライセンスのリモートアクセスコードを1つ公開して、Opusの学習データに入るようにしてみるべきだな
Fast.AIのディープラーニング講座を受けたとき、機械学習プロジェクトが引き込むPython依存関係の数に驚いた
Webフロントエンドのプロジェクトは常にサードパーティ依存が多いと思っていたが、自分には機械学習エコシステムの方がはるかに絡み合って見える
しかもWeb開発はセキュリティに敏感だと見なされ、長年にわたりセキュリティの知見や慣行が蓄積されてきたが、機械学習開発はずっと場当たり的で、一般的なソフトウェア工学の慣行もあまり適用されていないように思える
たとえば当時、機械学習モデルの配布方法の1つがPython pickleだったが、これは基本的に制限のない実行可能オブジェクトだ
この形式のモデルは、取り込むコンピュータ上で何でもできてしまい、この初期の無法地帯のようなエコシステムがセキュリティ侵害やサプライチェーン攻撃をより容易にしている可能性がある
やっているうちに少しコーディングを覚えた人もいれば、数学者もいるし、AIに酔った開発者のような人もいる
「コードはもう重要ではなく、動けばいい」という考え方もある
多くの人にとって、まともな依存関係管理は気にしたくない雑務にすぎない
いくつもの機械学習プロジェクトでこうした要素が重なっているが、実際には機械学習プロジェクトこそ再現性に最も注力すべき分野の1つだ
リポジトリ検索を見たところ、過去24時間に作成されたリポジトリのうち、
"A Mini Shai-Hulud has Appeared"というテキストを含むものが2.2千件もある: https://github.com/search?q=A%20Mini%20Shai-Hulud%20has%20Ap...これはアカウント、たぶんGitHub認証/Actionsトークンが侵害された後、それを使ってリポジトリが作成されたことを示すサインに見える
前回もこういうことがあったのだから、教訓を得ていたはずだと思っていた
このマルウェアはあまり努力しておらず、Microsoftもあまり努力していないように見える
免責すると、pytorchを使ったことはないし、ソフトウェアセキュリティの慣行にも詳しくない
だが、pytorchでネットワークアクセスが必要になるシナリオがあまり思い浮かばない
コードベースのどこででも任意のモジュールをimportしてそのAPIを使えるのは、まずいように思える
追加のimport制限や静的解析が必要そうだ
言語がこういう問題を扱うための適切な抽象化を持っていないように思う
比較すると、Rustでは関数シグネチャを見るだけで内部コードを理解しなくても可変性やライフタイムが分かるのが良い
依存関係にも似たものが必要だと感じる
開発者は下位コードをのぞかなくても、すべての依存関係を簡単に監査して、「ああ、この依存関係は
eval()を使っているな」とか「ネットワークアクセスしているな」と分かるべきだモバイルアプリは権限を強制するのだから、開発者も特定の機能だけを許可リストに入れ、あらゆる機能を丸ごと受け入れずに済むべきではないか
一般化はしたくないが、とくにAI開発コミュニティは、他のあらゆる考慮よりも利便性を優先しているように見える
たとえば、プロジェクトが初回実行時に大きなモデルを自動ダウンロードするのが標準のようになっている
たいてい無効化はできるが、複数ライブラリにまたがるコードクラスの深い階層のせいで、正しいパラメータを見つけるのが本当につらい
複雑なものを、たいていはおもちゃに近いものを、あまりに簡単に始められるのは良いことだが、この許容的な空気はかなり居心地が悪い
最初の問題解決ステップがいつも「
pip install …」であるように思えるし、一部の環境、たとえばMacOSではGPUアクセスの仮想化もうまくいかない今週、Pythonのバージョン管理にuvを使うのが良い考えなのか気になっていた
Webサイト[1]には「Pythonは公式な配布用バイナリを提供していないため、uvはAstralのpython-build-standaloneプロジェクトのディストリビューションを使う」とある
それはこのGitHubリポジトリ https://github.com/astral-sh/python-build-standalone を指していて、そこではさらに https://gregoryszorc.com/docs/python-build-standalone/main/r... に言及している
自分の理解が正しければ、Pythonビルド用のソースコードをpython.orgから直接取ってきていないようにも見え、これがどれほど安全なのか確信が持てない
asdf[2]にも同じ懸念はあるが、asdfはpyenv[3]を使っていて、そちらの方がより公式に近い感じがする
Pythonのインストールには、uvとasdfのどちらがより良く、より安全なのか、説明できる人はいるだろうか?
[1] https://docs.astral.sh/uv/guides/install-python/
[2] https://github.com/asdf-community/asdf-python
[3] https://github.com/pyenv/pyenv/tree/master/plugins/python-bu...
そもそも他のどこから取るんだという話だ
[1]: https://github.com/astral-sh/python-build-standalone/blob/a2...
uvとcpythonについてはあまり心配していない。プロセスは堅牢で、対応も速く、今では資金もかなりある心配なのは、たとえば
mdformatのように広く使われているが、主に1人が余暇で保守しているフォーマッタや、何年も更新されておらず、依存ツリーの3段階下にあるような非常に特定の依存関係だ活発に開発中のアプリで、すべての更新を固定して手動承認したくはないが、真面目なアプリなら今やそれが必須に見え始めている
その間に、暗号化されていない
.envファイルからAPIキーを取り出しておこう大規模なコンシューマー向けWebアプリで被害に遭うのは恥ずかしいが理解はできるとしても、同じホストやシステム上にたまたまある、おもちゃのデモ用リポジトリの間接依存のせいで数百〜数千ドル失うのは痛すぎる
こういう形でキーを盗まれた場合、OAIやAnthropicは返金してくれるのか知っている人はいる? それともユーザーのミス扱いなのだろうか?
Pythonバイナリを彼らがビルドするか、別の誰かがビルドするかで、危険性がどれほど変わるのか分からない
最近の自分の
pip installの大半はClaude Codeが提案し、自分はそのままEnterを押しているだけだモデルは数か月前のデータで学習されているのだから、今週何が侵害されたか知るはずがない
「このパッケージは今安全か」を判断するうえで最悪のフィルタを作ってしまった
Claude Codeにインターネット上のインストール用ソフトウェアを推薦させ、それをそのままインストールしているという話だろう
Claude CodeやどのLLMであれ、「このパッケージは今安全か」を判断するフィルタだと提案しているのは聞いたことがないし、述べられた理由も含めて、非常に悪いヒューリスティックに見える
setup.pyが自分のマシンで何を実行するかは分からない実行前にパッケージを実際に検査しているわけではないからだ
必要なのは、実行前にメタデータを取得して、どんなフックがあるか確認するツールだ
Claude Codeはほぼ毎日、ときには1日に何度も更新される
いつかAnthropicが侵害されたら、私たちは皆ひどい目に遭うだろう
とはいえ、最近は何もかもYOLOだ
GitHubで4月20日に投稿されたこのメッセージを見かけたのだが、少し混乱している
"deependujha hi @thebaptiste, thanks for inquiring. Release of 2.6.2 is blocked due to some internal reasons. Will notify once release is made."もしその時点から問題を把握していたのに今まで警告していなかったのだとしたら、本当に嫌だ
もっと知っている人が明確に説明してくれるとありがたい
https://github.com/Lightning-AI/pytorch-lightning/issues/216...
それ以前に影響を受けた配布物はなく、流出についても把握していませんでした
GitHub上の元のリリースには問題はありませんでしたが、混乱を防ぐために取り下げています