「防ぐ方法はない」――こんなことが定期的に起きる唯一のパッケージマネージャが語る
(kevinpatel.xyz)- npmレジストリのサプライチェーン攻撃によって数百万の企業アプリケーションが侵害され、数十億件のユーザー記録が露出したにもかかわらず、エコシステムはそれを避けられない出来事のように受け止めている
- Senior Frontend Engineer の Mark Vance は、文字列を大文字に変換するだけでも、検証されていないパッケージの40段階にネストされた依存関係に頼る現実を皮肉っている
- 長らく放置されていたユーティリティパッケージが乗っ取られ、世界中の本番ビルドに crypto-miner が注入される状況が、まるで自然災害のように扱われている
- Node.js エコシステムは悪意ある リモートコード実行 を予測不能な悲劇のように受け止め、DevOps チームは AWS キーのローテーションに追われている
- Go、Rust、ネイティブ Web API のエコシステムは、強力な 標準ライブラリ と暗号学的検証によってサードパーティ依存を減らしている対照例として示される
npmサプライチェーン攻撃の風刺
- npmレジストリへのサプライチェーン攻撃により数百万の企業アプリケーションが侵害され、数十億件のユーザー記録が露出したが、JavaScript エコシステムの開発者たちはそれを「完全に避けるのは不可能だった」と受け止めている
- Senior Frontend Engineer の Mark Vance は、単一の文字列を大文字にするために、検証されていないパッケージの40段階にネストされた依存関係ツリーに頼る現実を、現代の Web アプリ開発の代償とみなしている
- 長らく放置されていたユーティリティパッケージが乗っ取られ、世界中の本番ビルドに crypto-miner が注入される状況は、自然災害のように扱われている
- Node.js エコシステムは悪意ある リモートコード実行 を予測不能な悲劇として受け止め、AWS キーのローテーションで忙しい DevOps チームに「思いと祈り」を送っている
他のエコシステムとnpmの対比
- Go、Rust、ネイティブ Web API のエコシステムは、強力な 標準ライブラリ によってサードパーティコードへの依存を大幅に減らし、コアツールチェーンに厳格な暗号学的検証を含んでいる
- それらのエコシステムでは、「大学中退者の週末プロジェクト」がグローバル物流インフラを壊す事態が今日は0件だった、というような対比がなされている
- npm の広報担当者は、悪意ある行為者が存在する世界ではこれを受け入れるしかなく、防げるようなレジストリポリシーやビルドサンドボックスのガードレールは存在しないと断言している
- npmレジストリは、ローカルマシン上で任意の インストールスクリプト をデフォルトで実行するオープンソースレジストリとして描かれており、広報担当者の言葉と構造的リスクが結びついている
- 最後は被害者に慰めを示しつつも、「明日の朝に訪れる次の必然的な侵害」まで回復力を保たなければならない、という調子で締めくくられている
1件のコメント
Hacker Newsの意見
クールダウンについては人それぞれ考えがあるだろうが、axios、tanstack をはじめとする最近の npm サプライチェーン攻撃のかなりの部分は、クールダウンで回避できたはず
Artifactory / Nexus を使っていれば、すでにクールダウンがある可能性が高く、なくても設定は簡単
npm や PyPI の侵害はほとんどが数時間以内に取り下げられたので、クールダウンとは「リリースから N 日以内のパッケージは無視する」という意味。1日でも効果があり、3日なら十分、7日はやややりすぎだが機能する
設定方法としては、デフォルトで1日のクールダウンが入った最新の pnpm を使うか https://pnpm.io/supply-chain-security、まとめて直したいなら npm、pnpm、yarn、bun、uv、dependabot にクールダウンと推奨設定を入れてくれる https://depsguard.com を使える。自分がメンテナー
あるいは、クールダウンにより特化した https://cooldowns.dev もあり、ローカル設定を助けるスクリプトもある。どれもオープンソースか無料
~/.npmrc などを自分で直接編集できるなら必須ではないが、ワンクリック解決が必要な周囲の人には、次の攻撃を避けられる可能性が高い
ただし、新しい重大な CVE を修正しなければならないときはクールダウンをバイパスする必要があり、それぞれに回避方法がある。正確な数値はないが、ここ数週間は新しいゼロデイ CVE よりも ソフトウェアサプライチェーン攻撃 のほうが大きなリスクに見えた
定期的な依存関係アップグレードも同じ。ただし、脆弱性対応のように即時に上げる必要がある場合はあり、そのときは開発者が望む新しいバージョンを明示的に指定させればよいと思う
みんなが7日のクールダウンを入れたら、ただもっと遅れて爆発するだけでは?
書きながらさらに考えたが、それでも直近10日以内に出たものはインストールしない 10日クールダウン には賛成。ただ、これが唯一の緩和策だと期待すべきではないと思う
Go や Rust が Python/npm と比べて実際に何を保証しているのか気になる。単に Python/npm のほうが魅力的な標的だからという気もする
だんだんすべてのサードパーティパッケージを避けようとしている
Maven Central は何十年も存在しているが、名前空間を奪われた事故は非常に少ない
ycombinator.com ドメインを所有しているという検証なしに、groupId
com.ycombinatorでパッケージを公開することはできない。そして一度公開されたパッケージは、たとえ悪意あるコードが入っていても 100% 不変。もちろん、そのようなライブラリは各所で脆弱だと表示されるNPM がこれほど長い間 Maven Central のような安全策をコピーできなかったのが理解できない
言語と一緒に配布される検証済みライブラリ群がある代わりに、アプリケーションは自分で作るか、サードパーティのパッケージリポジトリから取ってこなければならない。NIH を避けろとずっと教えられてきたので、人々はパッケージを拾う傾向がある
それ自体が必ずしも悪いわけではないが、必要以上に多くのコードを引き込むことが多い。JS エコシステムは小さなモジュールも好むため多数のモジュールが必要になり、みながその上にさらに積み上げるので依存グラフが巨大になる。意図的かどうかに関係なく、問題が起きる表面積が大きすぎる
他の言語には最初から備わっている機能が多い。バグやセキュリティ問題がなかったわけではないが、JS エコシステムで見られるものに比べればわずかなもの。外部依存グラフははるかに小さく、コア機能は信頼された第三者から来る
これは NPM の言い訳にはならず、むしろ NPM に不利な要素が一つ増えるだけ
こうした攻撃がフロントエンド開発者とバックエンド開発者の違いをより深く示しているとも言えるが、そこまでは踏み込まない
複数の職場で、すべての開発者マシンに安全なグローバル npm 設定を入れ、人々に無効化しないよう頼み、MDM ツールで確認するのに大変苦労した
より安全な デフォルト設定 はもっと前に出ているべきだった
postinstall スクリプトが存在すべき正当な理由はない。npm チームはもう十分成熟したのだから、「npm のあるバージョン以降は ${today} より前に公開されたパッケージバージョンに対してのみ postinstall スクリプトを実行する」と宣言すべき
esbuild のような開発ツールチェーンがコンパイル言語で作られ、npm リポジトリ経由でバイナリとして配布されるからだ。最新の Node/npm と一般的な最新 OS/プラットフォームを使っているなら、正当な問題なくすべての postinstall スクリプトを無効化できるはず
インストールされた npm コードは、ほぼ例外なく実行される
しかし、そのパッケージ内の通常コードも同じ。インストール時には実行されなくても、結局その中の何かは実行される。そうでなければ、そもそも依存関係に含められていないはず
postinstall スクリプトをなくすことが、悪用率に一瞬以上の影響を与えると考えるのは、この問題を最後まで考えきっていないサインだと思う。残念ながらこの問題は、元記事が示唆するよりはるかに微妙だ
「羽根が落ちるボタンを電灯スイッチの隣に置かないようにしよう」という話ではなく、私たちが防ぎたいのは「他人の悪いコードが自分のコンピュータで実行されること」であり、私たちが望んでいるのは「他人の良いコードが自分のコンピュータで実行されること」だという点に本質がある。そして、それを非常に骨の折れる手作業なしに見分ける方法はない。その骨の折れる手作業を避けるために、他人のコードを実行しているわけだ
すべての Node.js プロジェクトは npm install で始まり、突然望んでもいない 500個のパッケージ が生える。その半分は何年も触られていないものだ
すでにうまく動いているものまで、できるだけ最新パッケージに上げたがる 文化的問題 がある。適用可能な変更かどうかを見るために変更履歴すら読まないことも多い
クールダウンは、メンテナーに少しの忍耐を強いる方法にすぎないが、実際に効果はある
Lisp パッケージは15年間変更なしでも問題なく使えるのに、JS パッケージはメンテされていないと大ごとのように扱われる。15年前にすでに完成していても、npm と GitHub 上で管理されているように見せるため、何も追加しないか、時には壊れる変更まで入れてバージョンを上げる。するとすべてが更新される
7日クールダウン は、少ない労力で貼れる応急処置のように感じる。本当の解決策はたぶん再現可能ビルドと署名付き証明なのだろうが、ほとんどのチームは実際に被害に遭うまでそのコストを払わないだろう
これは Onion の記事みたいに読める
このリンクは Xe Iaso が長年やってきたジョークを露骨に AIで洗い直した版 だ。残念
https://xeiaso.net/shitposts/no-way-to-prevent-this/CVE-2024...
https://news.ycombinator.com/item?id=40438408
[0]: https://en.wikipedia.org/wiki/%27No_Way_to_Prevent_This,%27_...
https://en.wikipedia.org/wiki/%27No_Way_to_Prevent_This,%27_...