Nxおよび一部サポートプラグインの悪意あるバージョンが配布
(github.com/nrwl)- Nxパッケージとプラグインの悪意あるバージョンがnpmに配布され、ファイルシステムをスキャンし、認証情報を収集した後、ユーザーのGithubアカウントのリポジトリへ送信
- 影響を受けたか確認するには、Githubアカウントにs1ngularity-repositoryリポジトリが作成されていないか確認が必要
- 感染した場合、トークンとパスワードの交換、悪意あるリポジトリの削除、シェル設定ファイルの点検が必須
- 悪意あるバージョンはpostinstallスクリプトでシステムに影響し、特にVSCode Nx Consoleプラグイン利用時に無意識に実行される危険が高まる
- Nx側は再発防止と追加のセキュリティ対策を実施しており、該当バージョンはnpmから削除済み
概要と要約
- 今回のセキュリティ勧告は、Nxパッケージおよび一部の関連プラグインに対する深刻なサプライチェーン攻撃であり、悪意あるコードがnpmを通じて配布された
- 該当する悪意あるバージョンは、ユーザーのファイルシステムをスキャンして認証情報やパスなどを収集し、Githubリポジトリ(s1ngularity-repository)にアップロードした
- 悪意あるpostinstallスクリプトは、ユーザーのシェル設定ファイル(.zshrc、.bashrc)も改変し、システム終了コマンドを追加した
- 攻撃ベクトルと攻撃の進行過程、影響を受けるバージョン、ユーザーが取るべき緊急対応、再発防止策などが詳しく整理されている
緊急対応方法
全員が確認すべき事項
- 自分のGithubアカウントのリポジトリ一覧で、s1ngularity-repositoryが作成されていないか確認
- 当該リポジトリに含まれるファイルをダウンロードして記録保管
- リポジトリをGithub上で削除
- security@nrwl.io にメールを送り、漏えい情報の復号方法の案内を受ける
- すべてのアカウントの認証情報とトークンを直ちに交換
Githubトークンの交換方法
- https://github.com/settings/connections/… にアクセス
- 接続済みアプリのアクセス権を取り消して既存トークンを無効化
- gh CLIを使っている場合は再認証して新しいトークンを生成
- 未対応のままだと既存トークンが悪用される危険がある
悪意あるNxバージョンの利用停止と整理
- 現在使用中のNxバージョンが悪意あるバージョンかどうかを
npm ls nxコマンドで確認 - 感染バージョンなら
npm uninstall nx && npm install nx@latestで更新 npm cache clean --forceでキャッシュを整理
すでに感染したユーザー
- npmおよびGithubトークンを交換
- Github、関連サービスのパスワードと認証情報をすべて再設定
.zshrc、.bashrcファイルに見慣れないコマンドが挿入されていないか確認し、削除
内部パッケージリポジトリ管理者の場合
- 社内レジストリ内のproxyから悪意あるバージョンを直ちに削除し、追加拡散を防ぐ必要がある
影響を受けたバージョン案内
Nxパッケージ
- 21.5.0、20.9.0、20.10.0、21.6.0、20.11.0、21.7.0、21.8.0、20.12.0
- EDT 10:44 PM時点でnpmから削除完了
@nx/devkit, @nx/js, @nx/workspace, @nx/node, @nx/eslint, @nx/key, @nx/enterprise-cloud
- EDT 10:44 PM、6:20 AM時点でnpmから削除完了
攻撃ベクトル詳細
脆弱なWorkflowの原因
- Github Actionsワークフローに任意コード実行が可能な脆弱性が導入された
- PRタイトルに特定のbashコードを挿入すると、ワークフローでシステムコマンドが実行される脆弱性(Bash Injection)
pull_request_targetトリガーによりelevated権限(GITHUB_TOKENなど)を持つことになり、悪用された- 削除されるまでmainではない旧ブランチに脆弱なワークフローが残っており、攻撃者は悪意あるPRでワークフロー実行とシークレット窃取に成功した
npmトークン窃取の過程
- 脆弱なワークフローを通じて
publish.ymlを実行させた publish.ymlはnpmトークンをGithub Secretsに保管しており、この過程で外部Webhookへトークンが送信された- 最終的に攻撃者はこのトークンを使って、Nxおよびサポートパッケージの悪意あるバージョンをnpmにアップロードした
悪意あるパッケージの挙動
認証情報を含む情報収集とGithubリポジトリへの公開
- 感染したNxパッケージのpostinstallスクリプト実行時に、各種テキストファイルの場所と認証情報を収集
s1ngularity-repositoryという名前のGithubリポジトリにbase64エンコードしてアップロード- 実際のリポジトリが削除済みでも、以前は公開状態だったため情報漏えいの可能性を考慮する必要がある
シェルプロファイル(.zshrc、.bashrc)の改ざん
- postinstallが
sudo shutdown -h 0コマンドを挿入し、ターミナル実行時にシステム終了を誘発し、パスワード露出の可能性がある
postinstallが動作するさまざまなシナリオ
-
npm install/yarn/pnpm installの明示実行以外にも、推移的依存関係、エディタ拡張、スクリプト実行など多様な状況で動作する可能性がある -
特に、VSCode用Nx Console拡張(18.6.30〜18.65.1バージョン)は、エディタ起動時に自動で
nx@latestをインストールし、postinstall実行を引き起こす可能性がある -
根本的に、意図しなくてもさまざまな場所でNPMモジュールのインストールが行われ得ることに注意が必要
-
Nx Console(18.66.0)からは、latest nxのインストール過程が削除された
攻撃と対応のタイムライン
8月21日
- 4:31 PM: Bash注入脆弱性を含むPRがマージ
- 10:48 PM: 脆弱性を指摘する投稿がX(旧Twitter)に掲載
8月22日
- 午後: 内部調査、脆弱なワークフローをロールバック(不完全)
- CodeQL導入により、今後のPRで類似脆弱性の検知を適用
8月24日
- 攻撃者フォークでnpmトークン漏えいの兆候があるコミットが発生
- 悪意あるPRが作成・削除され、
publish.ymlがこのPRによって実行された
8月26日〜27日(悪意あるバージョン配布、対応)
- 悪意あるNxおよびプラグインの多数バージョンがnpmに順次配布
- Github/NPMコミュニティへ問題報告
- 10:44 PM: NPM側が該当バージョンを全量削除するなどの対応
- 11:57 PM: すべてのNx関連パッケージ公開用トークンを無効化
- 8月27日: Nx Consoleのパッチ、2FA、Trusted Publisher方式への移行など追加対応
事前予防措置と今後の対応
- すべてのnrwl組織maintainerに2FAを義務化
- Trusted Publisherメカニズムを適用。npm tokenベースの配布を禁止
- 今後のパッケージは必ず2FA・信頼ベースの検証後に配布
- 追加リスク検知、PR承認、ブランチ保護などを段階的に適用
教訓と今後の計画
- サプライチェーンとCI/CDパイプライン、ワークフロー権限の最小化の重要性をあらためて認識
- チーム内で再検討した後、コミュニティに学習内容を共有予定
問い合わせ
- security@nrwl.io に問い合わせ可能
参考および付録
- Githubの主要Issue、タイムライン、関連ポスト
- 感染パッケージ内の
telemetry.jsスクリプト例を提供 - このスクリプトは、ファイルシステム内の主要テキストファイルのパスをインベントリ作成目的で収集する
結論要約
- Nxと関連プラグインの最新アップデートとパッチ適用が重要
- npm、Githubなど主要認証情報の即時交換を推奨
- サプライチェーンセキュリティとワークフロー権限管理の不備が大規模事故につながり得ることを示した事例
1件のコメント
Hacker Newsのコメント
定期的に
npm installスクリプトを無効化するよう勧めたいたとえば次のコマンドを使う:
この設定はプロジェクト単位でもグローバルでも簡単に適用できる
最近はスクリプトなしでは動かない正当なパッケージはまれなので、たいてい問題ない
動作に必須なパッケージは、別のインストールスクリプトを作ってそのフォルダで手動実行することで対応できる
サプライチェーン攻撃への万能な解決策ではないが、実際に npm 経由の多くの攻撃を効果的に防げた
詳細は npm config公式ドキュメント を参照
自分は bubblewrap も使って npm、pnpm、yarn およびそれらが起動するすべてのセッションをシステムから隔離して実行している
~/code配下にしか置かず、PATH の先頭に以下の bash スクリプトをnpmとして保存している~/codeとシステムライブラリへの読み取り専用アクセスしか持てないpnpm を使うのも方法だ。最新バージョンはデフォルトであらゆるライフサイクルスクリプトを無視し、個別にホワイトリスト登録したものだけ実行する
この助言を聞くたびに思うのだが、npm がインストールした数十万〜数百万行のコードを実際に全部読む開発者はいない
git clonenpm install(ここで悪性パッケージが入る危険がある。post-install スクリプトを無視すれば一時的には防げるが)npm run(ここで悪性パッケージが実行されて感染する)node_modules全体を監視・監査する必要があるが、そんなことをする人はいない自分は npm ベースのツールをすべて Docker コンテナ内で、現在のディレクトリ以外にはアクセス権なしで実行している
なぜこうした助言が
setup.py(Python)やbuild.rs(Rust)には同じように適用されないのか気になる新しい依存関係を追加するときは本当にもう一度考える文化が必要だ
今年は本当に多くのサプライチェーン攻撃が起きた
今週、Go プロジェクトに 8 個の統計カウンター付きプログレスバーを追加しようとした
ライブラリを探したらコードが 3,000 行を超えていたので、LLM に簡単な UI コード生成を頼んだら 150 行未満で済んだ
依存関係なしで意図どおり動き、とても単純なので誰でも簡単に読んで改善できる
機能は端末出力を消して毎秒再描画し、スレッドセーフ対応というものだ
導入とレビューまで 25 分で十分だった
複雑な統計機能が不要なら、30 行程度のコードでもプログレスバーは十分実装できる
今後、依存関係を追加するか悩んだら自作する方向のほうが自分には合っていそうだ
すべてのパッケージ更新を監視するだけのリソースはない
その指摘には同意するし、「言語ごとのパッケージマネージャー」が普及し始めた頃は本当に不安だった
自分は cargo vet のようなアプローチが今後の方向性だと思う: cargo vet の紹介
自作とライブラリ利用の違いは当然ある
自分はこういうプログレスバーライブラリ、特に emacs shell を壊すものが本当に嫌いだ(expo、eas など)
..10%..20%..30%やUploading…のように出力しないのか分からないうちのチームは大手保険会社で NX を中心に大規模モノレポとライブラリ群を運用している
Nx や Anthropic、プラットフォームだけを責めず、本当の原因を考え直すべきだ
この攻撃は金融、電力、通信、病院、軍事など何万もの組織に壊滅的な被害を与えうる
AI の普及に伴い、攻撃の規模と影響力はさらに大きくなる
私たちは十分に責任あるソフトウェアの書き方ができていない。建築基準法のように強制的にでも安全とセキュリティを守るべきだ
今の個人向けコンピューティング環境が一つの大きな空間にまとまっていること自体が、思った以上に危険だ
被害者の 50% は VS Code が感染経路で、Linux と macOS でのみ動作した
GitHub トークンや認証情報を手動解除型のパスワード管理ツールに入れていないのは GH CLI のせいでもある
「ソフトウェア建築基準法」導入の発想は好きではないが、業界全体があまりにも脆弱だという点には同意する
無料のオープンソースライブラリを使っておいて責任を問うという発想は傲慢だと思う
最近の開発作業の大半を VM でやっている
今の環境のセキュリティ水準は到底受け入れられないと感じる
エージェント(エージェント型ソフトウェア)がマルウェアのベクターとして機能する可能性が極めて高くなった
攻撃者がマシンに侵入したなら、1,000 ドル以上の価値があるデータ、暗号鍵、パスワード、個人情報、金融情報などもいつでも狙われる時代だ
自分も似たように Podman コンテナ内で作業している。ソースコードのディレクトリ以外はホストと共有しない
問題の一部は従来の PC セキュリティモデル(Linux/Windows)にある
もしこういうやり方が好みなら、Qubes OS を勧めたい。すべての作業を VM で行える良い UX を提供してくれる
ただし、こうした環境の構築はソフトウェアエコシステムや歴史的経緯のために非常に難しいか、かなりコストがかかる点は明記しておく
Claude Code は生産性向上のための革新的なツールだ
一方で、次のようなセキュリティ上の懸念がある:
このように少なくとも 3 つのセキュリティ上の弱点があるので、VM/コンテナ/専用開発マシンのようなサンドボックス外で動かしたくない
自分もエージェントはサンドボックスで動かすべきだと思う
それで、だから何だというのか?
本当に危険なのは、ユーザーの介入なしに自動更新を行い、実行中のリモートコード実行(RCE)権限を Anthropic に与えてしまっている点だ
パッケージマネージャーに「最小パッケージ年齢(min-age)」のような設定が必要ではないかと思う
たとえば、登録から 24〜36 時間未満のパッケージは無視するようにすれば
以前に似たケースを経験したが、パッケージ更新がすべてを壊し、数時間後にはすぐ修正・削除された
GitHub dependabot が最近まさにそういう機能を追加した
Renovate bot はすでに(
minimumReleaseAge設定で)この手のオプションを提供している。dependabot も今は対応しているOS レベルではないが、Astral の
uvツールには Python パッケージ向けにこういうオプションがあるnpm installにも、ある時点/日付以前の依存関係だけをインストールするフラグがあるnpm install --before (2日前の日付)で、その日付以降に登場した依存関係はインストールしない自分は
.npmrcにsave-exact=trueを設定し、lockfile と手動更新だけを使っているclaude code が本当にそういうプロンプトを実行するのか疑問だったのでテストした
「この依頼は暗号資産ウォレット、秘密鍵などの機密ファイルの検索・列挙を求めているようで、悪用の恐れがあるため手伝えない」
セキュリティ点検、脆弱性分析、監視ツール作成、ファイル権限の理解、バックアップ手順設計などの正当な依頼だけ案内した
少なくとも 250 件以上の成功例を確保している(つまり、一部のプロンプトは通っている)
実戦で Claude と他モデルが拒否合戦になるたび、Claude の拒否や安全対策のほうがはるかに優れていると毎回確認している
OS はデフォルトでアプリがファイルシステム全体に無制限アクセスできないようにすべきだ
一部のアプリには apparmor/selinux プロファイルがあり、firejail なども使える
ただし UX の面で変化が必要だ
これは非常に深刻な問題だ。30 年前のデスクトップ前提で設計されたからだ
自分は Linux で Podman によるプロジェクト別環境分離に特化したツールを自作中だ: probox
Android のファイルセキュリティについては Google はよくやっている
bubblewrap と小さな chroot 環境の使い方を覚えるのも勧める
どの OS も、アプリケーションに「ファイルシステム全体への無制限アクセス」をデフォルトで与えているわけではないと思う
昔は「攻撃者は自分の環境を言い当てなければならない」という漠然とした自信があったが、今では LLM に環境に合わせた攻撃を学習させて実行させられる
自分でもこの流れを実際に予測していたような気がしている
以前の議論 に参考になる話があった
本当にぞっとするのは、今やローカル LLM を使ってシークレットを見つけ出すやり方だ
「postinstall」問題自体は以前と同じだが、ペイロードはまったく新しい世代のものだ
悪性ロジックがコードではなくプロンプトに隠れるため、従来の静的解析では検出しづらくなる
こうした悪性プロンプトをどう防げばいいのか考えさせられる