npm パッケージの unpublish に関するゴタゴタの大まかなまとめ
(最終更新:3月24日16:50ごろ)
事件の流れ
- kik の作者が同名の会社 KIK の
弁護士特許出願代理人からパッケージ名を変更するよう要請される - 作者が拒否したところ
弁護士代理人は npm の運営にコンタクトする - 運営が作者の許可なく
パッケージを unpublish するパッケージの所有権を移し替える - 作者がこれに反発し自身が所有する270あまりのパッケージをすべて unpublish する
- I’ve Just Liberated My Modules — Medium
- unpublish されたパッケージは npmjs.com からダウンロードできなくなる
- unpublish されたうちのひとつである left-pad に間接的に依存したパッケージが多数あったため世界中でビルドがぶっ壊れる
- 作者が npm 上の left-pad の所有権を他人に譲り渡す
- 新しい所有者が left-pad の再 publish を試みるも、同一バージョンは再 publish 不可
- 世界中でビルドがぶっ壊れ続け npm 社の CTO が居ても立ってもいられなくなる
- 新しい所有者の要求を受け、 CTO が管理者権限により unpublish の取り消しを実行する
- ビルドがぶっ壊れなくなったため、 CTO はぐっすり眠れそうとのこと
- その裏でとあるユーザーが unpublish されたパッケージの所有権を多数取得していた
- https://www.npmjs.com/~nj48
- 悪意ある者に取得されないよう有志が保護したというのが実情らしい(未確認)
- 3月24日12:00時点で、所有権は npm 運営の手に戻っている
何が問題だったのか
npm の仕様
- パッケージの所有者がパッケージを unpublish できるようになっていること
- メジャーなパッケージマネージャの多くは unpublish に相当する操作をユーザーに提供しない
- 代わりとして unlist (NuGet) や yank (Cargo) といった操作を提供することがある
- unlist/yank されたパッケージはリポジトリの一覧には表示されなくなるが、依存解決中にそのパッケージをダウンロードすることは可能
- 本当の緊急時のみリポジトリ管理者の手でパッケージが削除されることはある
- unpublish されたパッケージのネームスペースを他人が乗っ取れるようになっていること
- 同一バージョンの再 publish はできないものの、別のバージョンで悪意のあるコードを publish すると依存元パッケージを攻撃できる可能性がある
人的要因
- 代理人と作者のやりとりにおいてお互いの態度がよろしくなかったこと
- 法務関係の事態とはいえ、 npm 運営が作者の許可を得ず
パッケージを unpublish したパッケージの所有権を移し替えたこと- npm のパッケージ名に関する紛争解決ポリシーによれば、ユーザー間で問題が解決できなければ運営が調停するとされる
- 抗議のためとはいえ、作者が多数のパッケージを一度に unpublish したこと
- 混乱を招くことは承知していたようだが、 left-pad に依存する babel まで壊れることは予測していなかったと思う
- npm 運営が社内の合意もおろそかに unpublish の取り消しを実行したこと
関連記事
- npm 運営による事後の調査報告:The npm Blog — kik, left-pad, and npm
- KIK の中の人が公開した KIK の代理人と kik 作者のやりとり:A discussion about the breaking of the Internet — Medium
- kik 作者の記事の和訳:【意訳】たった今、npmのパッケージを解放しました。 - Qiita
- 自分のパッケージが今回 unpublish されたパッケージに依存していそうな場合:
- チェック方法:npmパッケージ非公開化問題の巻き添えを食らっているかチェックする - Qiita
- 依存している場合の対応:npm事件対応メモ - マルシテイア
- このような事態に備えて依存先パッケージを bundle すればいいという提案:How to not break the internet with this one weird trick — Medium
余談:
- 一般的なパッケージマネージャのつくりに興味がある人にはこの記事がおすすめ。 Go のパッケージマネージャを新規設計する視点から問題領域などを分析してる:So you want to write a package manager — Medium
- “パッケージ管理は厄介な領域だ。本当に厄介だ。表面上は純粋に技術的に解決可能と見える。そう考えて取り組んだ者は皆、避けがたい次なる結論に至る:ソフトウェアはおそろしい。人々はおそろしい。シナリオは無数にあり、何ひとつまともには動かない。証明可能なことに、何ひとつまともには動かない。人生とは逆巻くカオスとエントロピーの渦の中の無意味な摂動。”
感想
- JS 界隈に単機能モジュールを多数組み合わせて使う風潮があるため被害が広がったなという感じ
- unpublish 操作はユーザーに開放しないほうがいいと思う
- npm は他のパッケージリポジトリと比べてパッケージ数が桁違いに多いため、 npm 社としては unpublish を依頼制にしたくないんだろうけど
- パッケージ作者に無断で管理者がパッケージを削除することは、法に反するコンテンツを含む場合などはやむを得ないだろうが、今回のケースは微妙
- Objective-C/Swift のパッケージマネージャ CocoaPods は Pods ディレクトリ(依存先パッケージのソースコードを集約するディレクトリ)をバージョン管理することを推奨している。こうすると万が一依存先パッケージが削除されても影響を受けない。デメリットもあるがよいプラクティスだと思う
ブコメ返信
今回のケースではunpublishが禁止されても乗っ取りは防げるけどエコシステムの破壊は免れなかった。iOS詳しく知らないけどCocoaPodsはプラットフォーム限定できてビルド不要という違いがあるのでは。
ユーザーによる unpublish が禁止されていたとしたら、管理者権限での kik の unpublish によって依存関係が壊れることこそ免れないものの、その他多数のパッケージの突然の unpublish は為されず、被害は比較的小さく済んだはず。
CocoaPods で Pods ディレクトリのバージョン管理が現実的なのは、 Pods ディレクトリにパッケージのソースコードだけが保存されるから。ビルドは必要だが生成物は別のディレクトリに出力される。
ソースコードとプラットフォーム依存のバイナリを同じディレクトリに保存する npm や Ruby の Bundler などでは真似できなそう。