- NPMレジストリで1,000件以上のコンポーネントが数時間のうちに同じ手口で感染し、悪意あるコードを含む新バージョンが配布された
- 悪性パッケージはBunランタイムのインストールスクリプトを装って
setup_bun.js と難読化された bun_environment.js を追加し、実行時にTruffleHogを使ってローカル認証情報を窃取
- 収集されたAWS/GCP/Azure・GitHub・NPMトークンなどの機密情報は、
SHA1HULUD というGitHub Actionランナーを通じて外部へ送信された
- 悪性スクリプトは
npm publish を自動実行してワーム型の自己複製を行い、その結果27,000件以上のGitHubリポジトリが感染した
- オープンソースエコシステム全体にまたがるサプライチェーンセキュリティ脅威が改めて浮き彫りになった事例と評価されている
攻撃の概要
- 2025年11月24日、HelixGuardはNPMレジストリで1,000件以上のパッケージが数時間以内に同一手法で感染したことを検知
- 新バージョンはBunランタイムを追加するように見せかけ、
preinstall: node setup_bun.js スクリプトを含んでいた
- 同時に配布された
bun_environment.js ファイルは難読化された悪性コードで、実行時にTruffleHogをダウンロードして実行する
- TruffleHogはローカル環境からNPMトークン、AWS/GCP/Azure認証情報、環境変数などをスキャンして窃取
- 窃取した情報はGitHub Actionランナー
SHA1HULUD を作成し、Sha1-Hulud: The Second Coming. という説明を持つGitHubリポジトリ経由で外部へ流出
- HelixGuardは、この攻撃が2025年9月に発生した**「Shai-Hulud」事件**と同一攻撃者による可能性を示唆している
悪性コードの動作分析
- 例として
@asyncapi/specs パッケージを分析した結果、NPMに配布されたバージョンは感染していたが、GitHubの元リポジトリは安全だった
- 攻撃者は
package.json を改変して setup_bun.js を追加し、そのスクリプトが bun_environment.js を呼び出すよう構成
bun_environment.js は10MB超の高度に難読化されたJavaScriptファイルで、主な機能は次のとおり
- 環境変数からクラウド認証情報とトークンを収集
- TruffleHogによるシークレットキーのスキャン
- GitHub Actionsを通じたデータ流出
- さらに
package.json を改変して感染コードを挿入し、npm publish を自動実行してワーム型の拡散を行う
GitHub感染とデータ流出
- 悪性スクリプトは
.github/workflows/formatter_123456789.yml ファイルを作成し、SHA1HULUD ランナーを登録
- このワークフローはリポジトリのシークレットを二重Base64エンコードした
actionsSecrets.json ファイルにパッケージ化
- その後、
Sha1-Hulud: The Second Coming. という説明を持つランダム名のGitHubリポジトリを作成してデータをアップロード
- HelixGuardは27,000件以上のGitHubリポジトリが感染したことを確認
- 窃取された秘密情報には
AWS_ACCESS_KEY_ID, SLACK_WEBHOOK_URL, CODECOV_TOKEN, WEBFLOW_TOKEN など多様なサービスの認証情報が含まれる
感染したパッケージ一覧
- HelixGuardは数百件のNPMパッケージが感染したと報告
- 代表例として
@asyncapi, @ensdomains, @posthog, @zapier, @postman, @voiceflow など主要組織のパッケージが含まれる
- 各パッケージでは複数バージョン(例:
@asyncapi/specs@6.8.2, @postman/csv-parse@4.0.5)が感染
- 感染したパッケージの多くは正規のオープンソースプロジェクトを装っており、自動デプロイ過程で悪性コードが挿入された形となっている
セキュリティ上の示唆
- 今回の攻撃はサプライチェーンセキュリティの脆弱性を悪用し、大規模なオープンソースエコシステムを感染させた事例
- NPM・GitHub・クラウド認証情報など、開発インフラ全体のセキュリティ管理強化の必要性が浮き彫りになった
- HelixGuardは、感染したパッケージのインストールを直ちに停止し、関連トークンおよび認証情報をただちに失効させることを推奨している
5件のコメント
JSエコシステムは本当にめちゃくちゃなゴミ捨て場そのものです
シャイ=フルード再来:300超のNPMパッケージが感染
https://github.com/search/…
リアルタイムスキャナースクリプトを作ってみました。
疑わしいリポジトリのpathで
npx sha1-hulud-scannerと入力すればOKです。
ソースコード : https://github.com/developerjhp/sha1-hulud-scanner
Hacker Newsの意見
ひとつ共有したいコツとして、NPMの代わりに PNPM を使うのがよい
PNPM 10.x は複数の攻撃ベクトルを防いでくれる
1️⃣ デフォルトでは post-install スクリプトを実行せず、手動承認が必要
2️⃣ 新しいリリースが公開されてから一定期間(例: 4日)経過しないとインストールされないよう設定できる
NPM は本番 CLI 環境ではあまりに 不安定 だ
パブリッシャーキーは最小権限に制限し、特定のパッケージにだけバインドし、IP を CI/CD ランナーに固定するのがよい
ローカルに publish キーを置かず、必要なら OIDC Trusted Publisher やトークンベースのアクセスを検討すべき
lockfile だけでも5回は試しているのに、いまだに完璧ではない
構造やコミット履歴を見るとチームが懸命に改善しているのは分かるが、あまりに深い 穴 から始めている感じだ
いまだにファイル転送中の早期 EOF を検知できず、不完全なファイルをキャッシュに残すため、低速なインターネット環境では更新失敗で時間を大きく無駄にする
最初は複雑だが、シークレットを リース (lease) の概念で管理できる
CI ビルドごとにリースを作成し、終了時に自動で破棄され、TTL と自動ローテーションもサポートする
そのおかげで長期資格情報を隠し、ビルド時点でのみ短命のトークンを発行できる
この種の攻撃によって社内で本当の セキュリティ議論 が活発になるのは前向きなことだ
npm ciを使えばよいpackage-lock.json に明記されたバージョンだけをインストールするので、自動更新による攻撃リスクを減らせる
意図的な更新 だけを行う習慣が重要だ
pip install --only-binary=:all:オプションで似た保護を得られるソース配布を完全に遮断し、wheel だけをインストールする
ただしバージョン面で制約が出ることはある
uvでは--exclude-newerオプションで PNPM の「最小リリース期間」機能をまねできる自分はすべての依存関係を固定し、dependabot の通知を手動で確認している
これがやりすぎなのか、正しい習慣なのかはまだ考えているところだ
今日とくに関連する記事がある: "We should all be using dependency cooldowns"
依存関係の自動更新は、1日限りの脆弱性より危険な場合がある
すでに数千の lock file に広がった 感染済みパッケージ を巻き戻すほうがはるかに難しい
うまく動いているなら、わざわざ触る理由はない
uvではuv lock --exclude-newer $(date --iso -d "24 hours ago")コマンドで似た効果を出せる関連議論は issue #14992 にある
npx npm-check-updates -c 7コマンドで7日間のクールダウンを設定できるnpm-check-updates のドキュメント を参照
クールダウンは 0-day 脆弱性の拡散時間を長引かせる可能性がある
全員が同じクールダウンを使えば、発見の遅延 が生じるだけだ
PostHog の共同創業者 です
今回の攻撃の被害者だった
感染したバージョンは posthog-node 4.18.1, 5.13.3, 5.11.3 / posthog-js 1.297.3 / posthog-react-native 4.11.1 / posthog-docusaurus 2.0.6
キーとパスワードをすべて交換し、新しいバージョンを公開した
原因を分析中で、status.posthog.com に更新を出す予定
Web サイトが感染バージョンを配信していたなら、訪問者に被害があったのか知りたい
真面目な質問だが、Node で新規プロジェクトを始めるのは正しいのか
Astro で SaaS フロントエンドを作っているが、依存関係を更新するたびに不安になる
npm エコシステムの セキュリティ欠如 があまりに深刻に感じられる
Rust のように無数のサブパッケージに依存するエコシステムも、いずれ同じことを経験するだろう
C、C++、Odin のようにパッケージマネージャがないほうが、むしろセキュリティ上は賢明な選択かもしれない
最近は Deno の JSR をより信頼している
JSR ベースのパッケージは npm にもクロス公開されており、Deno 専用パッケージもある
たとえば Lume は遅いが安定した SSG として印象的だった
npm は最大のリポジトリなので、攻撃者にとって 価値が高い だけだ
RubyGems や Cargo でも十分起こりうる
単に最も広く使われるエコシステムだから攻撃が集中しているだけ
依存関係を慎重に管理し、毎日更新しなければよい
ページ描画に100個を超える依存関係を必要としない点が利点だ
プロジェクトリンク 参照
最近はすべての開発を Podman コンテナ の中だけで行っている
読んでいないコードは必ず隔離環境で実行する
完璧ではないが、最低限の セキュリティ習慣 だと思っている
セキュリティは通常 専門家に委ねられる 領域なので、現実には変えるのが難しい
12年前、NPM が一度完全に ダウン したことがあった
当時は単なるオープンソースプロジェクトだったが、今は Microsoft の所有だ
世界最大級の企業の一つなら、こうした問題を解決すべきではないのか?
それでも依然としてあまり変わっていない
エンタープライズライセンスで金にならないものは放置する
だから Windows 11 はマーケティングの塊のようだ
私たちは現在この攻撃活動を 監視中 で、感染したパッケージ一覧を Wiz ブログ で更新している
悪性ペイロードをリバースエンジニアリングしており、数時間以内に結果を共有する予定だ
PostHog の「Talk to a human」チャットが実際には ロボット応答 で不便だった
緊急サポートリンクも適切に案内されない
なので聞きたい ― どのバージョンを避けるべきなのか?
感染したバージョンは posthog-node 4.18.1, 5.13.3, 5.11.3 / posthog-js 1.297.3 / posthog-react-native 4.11.1 / posthog-docusaurus 2.0.6
最新バージョンに更新すれば安全だ
なぜいつも Node エコシステム でこうしたパッケージの混乱が起きるのか気になる
なぜこのコミュニティは複雑なインストールフックや自動更新をよいエンジニアリングだと信じているのか分からない
Node の創設者がすでに去った理由も理解できる
巨大なエコシステム、初心者開発者中心、セキュリティ意識の低さ、そして小さな機能ですらライブラリに依存する
Debian のように信頼できる管理者が検証すべきなのに、JS コミュニティはそれを ゲートキーピング として拒否する
だからこうした事態が繰り返される
そんな態度では何も変わらない
少し話は逸れるが、HelixGuard が何者なのか気になる
Web サイトはひどく、情報もほとんどない
顧客が暗号資産取引所だというが、何か怪しい
HelixGuard の X アカウント
2️⃣ 新しいリリースが配布された後、一定期間(例: 4日)が経過してからインストールされるように設定できる
すごく良い機能ですね。Google も時々、バグで動かないバージョンを NPM に上げることがあるので、自分のバグかなと思って焦ることがあります。