概況
- npm の 2016年3月の発表によると、パッケージ名
kikをめぐる紛争の末、メンテナーの Azer Koçulu がkikと left-pad を含む272のパッケージを公開取り消ししました。npm はその後毎分数百の障害を観測し、太平洋時間午後4時55分までに元の left-pad 0.0.3 を復元し、約2時間半の中断があったと報告しました。ダウンストリームのビルド失敗の正確な数は不明です。 - このインシデントはハッキングやマルウェア、left-pad のセキュリティ脆弱性ではありませんでした。その重要性はトポロジーとポリシーにありました。非常に小さなユーティリティが、名前紛争に関与しておらずレジストリの削除ルールを制御できない事業者が運営するプロジェクトにまで及ぶ依存関係チェーンの中に位置していました。
- npm の2016年の即時ポリシー対応と現在のルールを混同してはなりません。2016年のフォローアップでは通常の自己公開取り消しは24時間以内に許可され、古いパッケージの削除はサポートと依存関係チェックを経るものとしました。現在のドキュメントでは原則として72時間のウィンドウと公開依存関係がないことを条件とし、古いパッケージには追加の依存関係、ダウンロード数、所有権の基準を適用しています。また、現在のガイダンスでは非推奨化を継続性を維持する代替手段として提示しています。
- ここでいう「責任」とは、共有インフラの管理によって生じる運用上の責任を意味します。npm、メンテナー、Kik、その他の関係者が法的に責任を負うという判断ではありません。中心的な説明責任の問いは、レジストリが作成者の自律性を維持しながらも、一度の削除が依存関係グラフ全体に未検証の継続リスクを課すことを防ぐ方法です。
11行が問題の規模ではなかった
left-pad のよく知られた話は、抗しがたい矛盾から始まります。11行のコードと当時広く報じられた小さな JavaScript ユーティリティが消え、ソフトウェアのビルドが失敗し始めました。この説明が記憶に残るのは、パッケージがあまりに小さく重要には見えなかったからです。しかし、それだけでは不完全です。問題の規模は関数の長さではありませんでした。特定のパッケージバージョンが共通のレジストリから取得可能であり続けることを期待する依存関係パスの数と配置にありました。
パッケージはソースコードの複雑さでは取るに足らずとも、配布トポロジーにおいてはクリティカルになり得ます。開発者が直接選択したことはないかもしれません。アプリケーションがあるライブラリに依存し、そのライブラリが別のライブラリに依存し、最終的に left-pad を必要とするかもしれません。最終消費者はインストールが失敗するまでパッケージ名を知らないこともあります。その連鎖のどこにも left-pad が洗練されている必要はありません。必要なのは、グラフのどこかにあるパッケージマニフェストやロックの決定が、レジストリがもはや提供していないアーティファクトを指していることだけです。
だからこそ、このインシデントはプログラマーが短い関数を自分で書くことを拒否したジョークとして扱われるべきではありません。障害発生後の関数の再実装は、パッケージ、継続的インテグレーションジョブ、デプロイシステム、開発者マシンにすでに分散している過去の依存関係宣言を変えるものではありません。2016年3月の当面の問題は、有能なエンジニアがパディングロジックを再現できるかどうかではなく、自動リゾルバがダウンストリームメタデータが取得するよう指示した正確なオブジェクトを得られるかどうかでした。
また、このイベントは悪意のあるコードの話でもありません。公開記録によれば、left-pad がシステムを侵害したり、データを流出させたり、技術的な欠陥を悪用したわけではありません。害を与えた行為は可用性パスからの削除でした。この区別により、このケースは侵入対応ではなく、サプライチェーンの継続性の問題に位置づけられます。ソフトウェアサプライチェーンはコンポーネントが敵対的であるために失敗することもありますが、正当なコンポーネントがグラフにまだ必要とされている間に利用できなくなることでも失敗します。
エビデンスは狭いながらも重要な結論を支持しています。ネットワーク効果により、npm は便利な公開棚から依存関係の基盤へと変貌していました。その移行が起こると、レジストリポリシーは他の組織がインストール、テスト、ビルド、デプロイできるかどうかに影響を与えました。コードは小さなままでした。レジストリの責任は、その決定が共有依存の地点にあったために大きかったのです。
名前紛争が関与していない関係者にまで及んだ
npm 自身の説明では、公開取り消しはkikパッケージ名をめぐる紛争の中で行われました。この紛争にはメンテナーと Kik メッセージングサービスに関連する企業が関与していました。npm はその名前空間の管理について決定を下しました。その後 Azer Koçulu がkikとその他272のパッケージ(left-pad を含む)を公開取り消ししました。
選択された公開資料は、その紛争を商標訴訟として判断するものではなく、裁判所の判決を示すものではなく、すべての当事者の法的権利を決定する完全な記録を提供するものでもありません。したがって、このインシデントを名前に関する法的評決に変えることは無責任でしょう。公開取り消しという行為から悪意を推測することも同様に無責任です。確認された点はよりシンプルです。あるパッケージ名に関するプラットフォームの決定の後、メンテナーが当時利用可能だった削除権限を、はるかに多くのパッケージにわたって行使したということです。
結果として生じた被害は元の関係内に留まりませんでした。ダウンストリームのメンテナー、企業、開発者はkikをめぐって交渉していたわけではありません。彼らは npm に名前の移管を依頼したわけでもなく、パッケージ作者に公開を続けるよう依頼したわけでもありません。しかし、無関係のパッケージが単一のアカウントレベルおよびレジストリレベルのアクションサーフェスを共有していたため、彼らのビルドパスは結果にさらされました。
紛争と爆発範囲のこの分離が、最初の説明責任の教訓です。レジストリには名前、なりすましの懸念、所有権の紛争、放棄を解決するプロセスが必要かもしれません。メンテナーが参加をやめる正当な理由もあるでしょう。しかし、ある紛争を解決または抗議するために使われるメカニズムが、明示的な継続性レビューなしに、無関係の依存関係チェーンに回避可能な障害を伝達できるものであってはなりません。
したがって、このインシデントは一人の人間の反応にすべての責任を負わせることで説明できません。レジストリは利用可能なアクションを定義し、依存関係グラフをホストし、名前を裁定し、アーティファクトを復元する能力を持っていました。パッケージ作者は依存関係を選択しました。アプリケーションチームはそれらを消費しました。各アクターは異なる制御層を占めていました。説明責任は、各義務をそのアクターが実際に持っていたコントロールに一致させることから始まります。
タイムラインがバージョンの同一性の重要性を示す
npm の2016年3月の再構成は、限定的な運用クロノロジーを提供しています。太平洋時間午後2時30分頃以降、npm は毎分数百の障害を観測しました。これはレジストリ側でのインストール障害の尺度であり、影響を受けたユーザー、プロジェクト、または本番サービスの総数ではありません。急速な伝播を示す一方で、最終的な人口は不明のままです。
代替の left-pad 1.0.0 は約10分以内に登場しました。通常の人間の説明では、失われたユーティリティが戻ってきたように聞こえるかもしれません。しかし、依存関係の解決はそれほど寛容ではありませんでした。一部のチェーンは特に 0.0.3 を要求していました。新しい 1.0.0 はそれらの要件を満たさなかったため、同じパッケージ名の下で機能的に類似したコードが存在しても、壊れたすべてのパスが復元されたわけではありません。
その詳細は、パッケージの行数よりもはるかに重要です。パッケージシステムは、バージョン制約と不変の同一性を契約の一部として扱います。リゾルバは通常、実装が短いという理由だけで新しいメジャーバージョンで十分だと判断することはありません。また、そうあるべきでもありません。バージョン境界を越えた自動置換は、別の種類の整合性と互換性リスクを生み出します。
npm は太平洋時間午後4時55分までに元の left-pad 0.0.3 を復元しました。その説明では、中断は約2時間半続きました。これらのタイムスタンプは対応の流れを説明するのに十分具体的ですが、裏付けのない普遍的なダウンタイムの主張に変換されるべきではありません。個々の開発者や自動化ジョブは異なるタイミングで障害に遭遇した可能性があり、公開情報源はその分布を定量化していません。
このエピソードは、しばしば一つにまとめられる3つの段階を示しています。トリガーはパッケージの削除でした。伝播は依存関係メタデータとレジストリからの新規取得を通じて発生しました。回復には、それらの依存関係チェーンが受け入れるバージョン同一性の復元が必要でした。代替品の公開は、コードの可用性だけでは不十分であり、継続性は期待される名前とバージョンの座標に依存していたことを示しています。
現在のパッケージおよびリポジトリページは、left-pad に関連付けられたオブジェクトを特定し、後のバージョンやメンテナンス履歴を示すのに役立ちます。しかし、それらだけでは、2016年の中断の各分における正確なレジストリ状態を再構築することはできません。歴史的な npm の説明がインシデントのタイムラインを管理しています。後続の npm および GitHub ページは継続性の記録であり、タイムマシンではありません。
レジストリは取得を制御する以上、受動的ではない
公開パッケージレジストリを中立的なストレージと表現するのは魅力的です。作者がアーティファクトをアップロードし、ユーザーがダウンロードし、プラットフォームは単に両者をつなぐだけです。left-pad 事件はその比喩の限界を露呈しました。npm は名前を割り当て、アカウント権限を実施し、公開取り消し操作を提供し、自動化されたクライアントのためにパッケージを解決し、障害率を観測し、最終的に失われたバージョンを復元しました。これらはインフラ機能です。
インフラの地位は、レジストリがすべてのボランティアプロジェクトを永久に維持することを保証しなければならないという意味ではありません。それは、レジストリ自身のルールと制御プレーンが予見可能なダウンストリーム効果を持つことを意味します。何百万もの自動化された決定が、名前付きバージョンが存在するかどうかを答えるために中央サービスに依存している場合、消失を管理するルールは可用性の制御です。
レジストリはまた、リスクを生み出す同じネットワーク効果から利益を得ています。簡単な公開はメンテナーを引き付けます。大規模なカタログはユーザーを引き付けます。標準化された解決はツールがサービスを深く統合することを促します。より多くの消費が公開をより価値あるものにし、それが中心性を強化します。その代償として、局所的なガバナンスエラーや境界設定の不十分なアクションが、はるかに大きなグラフ全体に伝播する可能性があります。
これが最も明確な形での運用責任です。責任は集中管理と予見可能な伝播に従います。この用語は不法行為の損害賠償、契約違反、または司法判断を主張するものではありません。どの当事者が可用性障害を防止、検出、封じ込め、修復できるかを問います。npm は公開取り消しポリシーを変更し、アーティファクトを復元できました。個々のダウンストリームユーザーはそれができませんでした。
だからといってダウンストリームの責任がなくなるわけではありません。ソフトウェアチームは依存関係の宣言方法、ロックファイルの使用、キャッシュ内容、ミラーリングするアーティファクト、クリーンインストールのテスト方法、維持するフォールバック手順を選択します。しかし、これらの制御はレジストリのポリシー層の下で動作します。消費者は露出を減らすことはできても、無制限の公開削除ルールを他の全員にとって安全にすることはできません。
有用な区分は「プラットフォームの過失」対「開発者の過失」ではありません。それは制御固有の義務です。レジストリは名前空間と削除を管理します。メンテナーは公開と宣言されたサポートを管理します。パッケージ作者は直接的な依存関係の選択を管理します。アプリケーション運用者は再現性と復旧態勢を管理します。回復力のあるエコシステムにはこれら4つの層すべてが必要であり、どのアクターも別の層の可能な予防策を自らの無視の言い訳にしてはなりません。
npm の認めたことが説明責任の枠組みを変えた
インシデント後の npm のフォローアップは異常に重要です。なぜなら、同社は中断を単なる不合理なメンテナーの行動や不注意な依存関係の選択として枠付けしなかったからです。同社は無制限の公開取り消しをシステム障害として特定し、実質的に「ボールを落とした」と述べました。同社は、高度に相互依存したレジストリが削除を私的な結果しか持たない私的な行為として扱うことはできないことを認識していました。
その認めたことは、質問をエチケットからガバナンスへとシフトさせました。メンテナーの行動は依然として重要であり、依存関係の選択も重要ですが、レジストリは以前のルールが予測可能な種類の中断からコミュニティを保護できなかったことを認めました。ポリシーは、性格だけでなく、根本原因の一部でした。
個人の非難は運用上弱いものです。たとえすべての観測者が一人の参加者が悪質に振る舞ったことに同意したとしても、その判断は次のメンテナー、侵害されたアカウント、誤ったコマンド、所有権紛争、またはバーンアウトによる退出が同じ結果を生み出すのを防ぐことはできません。プラットフォームの制御は、許可されているが影響の大きいアクションのために設計されるべきであり、協力的なユーザーが避けると期待されるアクションのためだけではありません。
npm の対応はまた、依存関係の外部性を認めました。公開取り消しは、作者のコピーを棚から引き揚げるだけではありません。削除された座標を必要とするすべてのダウンストリームパッケージを壊す可能性があり、その影響は数千のプロジェクトに及ぶ可能性があります。このインシデントで影響を受けた正確な数は不明のままですが、そのメカニズムはルール変更を正当化するのに十分明白でした。
責任あるインシデント後声明は、4つのことを行うべきです。失敗した制御を特定し、結果を誇張せずに述べ、即時の修復を説明し、再発を許した条件を変更することです。npm の歴史的な投稿はその構造の多くを提供しました。それらは紛争と復元を説明し、無制限の削除をガバナンス問題として特定し、改訂されたプロセスを発表しました。
公開記録は依然として、すべての内部決定、アラート、承認、サポートのやり取りを明らかにしていません。組織的な根本原因マップを完全に確立することはできません。しかし、npm 自身のポリシー診断は、回顧的なフォークロアよりも強い証拠です。レジストリを運営する企業が、古い公開取り消しモデルは相互依存エコシステムには不十分だったと述べました。その認めたことは説明責任分析の中心に残るべきです。
2016年のポリシーは直接的な修復であり、現在のルールではない
2016年の即時ポリシー対応は、一方的な削除に境界を設けました。npm は作者が24時間未満のバージョンは引き続き公開取り消しできるとしました。古いパッケージについては、作者は npm サポートに連絡する必要があります。サポートは削除が他のインストールを壊すかどうかを検討し、依存関係が存在する場合は、調整や所有権移管などの方法を模索し、安易に消失を許さないようにします。
その設計は、パッケージの経過時間を依存関係の大まかな代理として扱いました。新しく公開された誤りは採用がほとんどなく、迅速な撤回の正当な必要性があるかもしれません。古いアーティファクトは依存関係チェーンに入り込む時間がより多くあります。経過時間は爆発範囲の完全な尺度ではありませんが、24時間のしきい値は、私的な修正が公的な中断になる可能性がより高い時点に摩擦を生み出しました。
サポートゲートは人間の判断を追加しました。誰がパッケージに依存しているか、なぜ削除が要求されたか、メンテナーの利益とダウンストリームの継続性の両方を維持する別の救済策があるかを尋ねることができます。これは作者にプロジェクトのサポートを強制する約束ではありません。メンテナンスを終了することと、取得可能なアーティファクトを消去することの区別でした。
npm はまた、すべてのバージョンが削除された後の名前のセキュリティプレースホルダーについて説明しました。その目的は、空いた名前が悪意を持って取得され再利用されるのを防ぐことでした。そのポリシーは、削除によって露呈した2番目のリスクに対処しました。消失は現在のビルドを壊す可能性があり、無制御の名前空間リサイクルは将来のインストールを無関係の関係者のコードに向ける可能性があります。
プレースホルダーのアイデアは、可用性と整合性を分離できない理由を示しています。取得の復元だけで名前を保護しなければ、置換リスクを招く可能性があります。名前を恒久的に空にすることで保護すれば、整合性は維持される一方で、依存するビルドは壊れたままになる可能性があります。レジストリガバナンスは、アーティファクトとそれを指し示す識別子の両方を管理しなければなりません。
重要なのは、24時間ルールは npm の2016年の対応に属するということです。これは制度的学習の歴史的証拠であり、現在のポリシーを述べたものではありません。それを今日のしきい値として繰り返すことは、その後のポリシー開発を消去し、メンテナーに不正確なガイダンスを与えることになります。現代のルールは異なる条件を使用しており、現在のドキュメントから読み取る必要があります。
現在の npm ルールはより明示的な爆発範囲テストを適用する
現在の npm ドキュメントは、2016年の即時発表とは実質的に異なります。一般的には、公開レジストリ内の他のパッケージが削除対象のパッケージに依存していない場合に限り、72時間以内の公開取り消しを許可しています。したがって、時間だけでは十分ではありません。公開依存関係が存在する場合、最近公開されたものでも一方的な削除は拒否される可能性があります。
72時間より古いパッケージについては、現在のドキュメントではより厳しい一連の基準を適用しています。公開依存関係がない、過去1週間のダウンロード数が300未満、単一の所有者またはメンテナー。セルフサービスの条件を満たさないパッケージは、通常のコマンドパスを通じた黙示の削除ではなく、サポートの関与が必要です。
これらの条件は、3つの異なる形式の依存関係をコード化しています。公開依存関係は明示的なグラフエッジを明らかにします。週間ダウンロード数は、依存関係メタデータが全オーディエンスを示さない場合でも、限定的な需要シグナルを提供します。複数の所有者は共有ガバナンスの利害を示し、一人の人間による一方的な決定の正当性を低下させます。いずれも完全な爆発範囲モデルではありませんが、合わせると時間だけよりも情報量が多くなります。
現在のドキュメントはまた、公開取り消しされたパッケージまたはバージョンがレジストリから利用できなくなることを明確にしています。その結果こそが、公開取り消しが表面的なプロフィール変更ではなく、影響の大きいアクションとして扱われる理由です。ポリシーは、公開者のページを整理する能力ではなく、他のユーザーのインストールを保存することを中心に設計されています。
これらの公開ルールが証明できることには限界があります。それらは宣言されたポリシー表面を示すものであり、すべてのサポート決定や技術的執行経路の完全な監査ではありません。例外がどの程度要求され、承認され、すべてのプライベート依存関係が可視であるかは確立していません。公開依存関係チェックは必然的にレジストリが観測できるものに焦点を当てます。
それでも、進化は意味があります。2016年のルールは主に非常に新しいバージョンを古いものから分離し、古い削除をサポートに移しました。現在のルールは、依存関係、使用状況、所有権のシグナルを適格性に組み込んでいます。これは、事前アクションリスクテストとして表現された制度的学習です。
ソーステキストは npm の公開ドキュメントリポジトリでも入手可能です。これにより、メンテナーとエコシステムの観測者は書かれたルールのバージョン管理されたビューを得ることができますが、レンダリングされたドキュメントが運用上のユーザーガイダンスであり続けます。リポジトリのコピーは独立したポリシー権限と誤解されるべきではなく、npm のドキュメントの別の表現です。
成熟したレジストリは、アクションの時点でそのような区別を目立つようにするべきです。ユーザーは、削除が非推奨化と異なること、公開依存関係が重要であること、サポートレビューが必要になる可能性があることを理解するために、10年前のインシデントの知識を必要とするべきではありません。コマンド、ドキュメント、サポートプロセスが同じ爆発範囲ロジックを伝達するとき、制御は最も強力になります。
非推奨化はサポート終了と取得中断を分離する
現在の npm ガイダンスは、非推奨化を妥協案として提示しています。メンテナーは、パッケージやバージョンが推奨されなくなった、またはサポートされなくなったことをユーザーに伝えつつ、既存の依存関係チェーンが機能し続けるようにアーティファクトを保存できます。警告は、メンテナンスの決定を即座の消失に変えることなくインストーラーに届きます。
その分離はボランティアの自律性にとって不可欠です。メンテナーは、問題への対応、パッチのレビュー、セキュリティガイダンスの提供、互換性の保証ができない、または望まない場合があります。レジストリポリシーは、一度公開すれば生涯の労働義務が生じることを示唆するべきではありません。非推奨化により、作者は積極的な約束を終了しつつ、歴史的オブジェクトを利用可能に保つことができます。
継続性は、非推奨化されたソフトウェアを永久に安全または望ましいものにするわけではありません。非推奨化メッセージは放棄を警告し、代替を指し示し、選択されるべきでなくなったバージョンを特定できます。ダウンストリームチームは依然として移行、セキュリティ評価、サポートされていないコンポーネントの削除を行う必要があります。取得の保存は時間を稼ぐものであり、ライフサイクルリスクを排除するものではありません。
だからこそ、多くの場合、非推奨化は削除よりも優れています。障害モードを突然のビルド中断から可視の移行シグナルに変えます。チームは警告を観察し、作業を計画し、代替案をテストし、自身のリスクに適したスケジュールで更新できます。レジストリは再現性を維持しつつ、メンテナーは撤退を伝達します。
非推奨化はまた、証拠を生み出します。サイレントなアーティファクトはメンテナーの意図を示しません。欠落したアーティファクトは取得が失敗したことだけをユーザーに伝えます。非推奨化通知は、何が変わったか、どのようなアクションが推奨されるかを示すことができます。優れたレジストリ設計は、そのメッセージをバージョンメタデータとともに保存し、ユーザーがサポートされていない、侵害された、置き換えられた、単に非アクティブなパッケージを区別できるようにするべきです。
妥協は完璧ではありません。一部のユーザーは警告を無視します。一部の依存関係チェーンはそれらを隠します。一部の放棄されたパッケージは何年も埋め込まれたままです。しかし、公開依存関係が存在する場合、不完全な警告と継続的な可用性は通常、消去よりも破壊的ではありません。ポリシーは、ソフトウェアのメンテナンスを停止する権利は、他人の歴史的ビルド入力を無効にする権利と同じではないことを認識しています。
名前空間の安全性は継続性の一部である
削除は、古いターボールが取得可能かどうかという問題を超えて、名前はどうなるのかという疑問を提起します。パッケージ名は信頼の座標です。ドキュメント、マニフェスト、チュートリアル、開発者の記憶は、インストール要求をそれらに向けます。削除された名前が無関係の公開者によって即座に要求される可能性がある場合、将来のユーザーは確立された経路をたどっていると信じながら、まったく異なるものを受け取る可能性があります。
npm の2016年のセキュリティプレースホルダーに関する議論は、その危険性に対処しました。レジストリは、悪意のある再利用を防ぐために、完全に削除された名前を予約することができました。依存関係スカッターパッケージに関する別の歴史的な npm の投稿は、一見空または依存関係関連の名前空間がセキュリティ上の結果をもたらす理由の文脈を提供します。教訓は left-pad 自体が悪意があったということではありません。削除が識別子をめぐる脅威表面を変えるということです。
これにより、三方のポリシー問題が生じます。名前を解放することは名前空間の可用性を向上させる可能性があります。名前を予約することは確立された期待を保護します。古いアーティファクトを取得可能に保つことはビルドを保護します。レジストリは、観測可能な条件の下でどの利害が優先されるかを決定し、紛争、移管、放棄がどのように扱われるかを説明しなければなりません。
所有権の移管は、アイデンティティと継続性の両方を保存できる場合がありますが、同意、本人確認、範囲、明確なコミュニケーションが必要です。新しいメンテナーは、古いメンテナーが去ったという理由だけで黙示的に信頼を継承するべきではありません。プレースホルダーは日和見的な再利用を防ぎますが、継続的なメンテナンスを提供しません。非推奨化は取得を保存しますが、ユーザーをサポートされていないコードに残す可能性があります。各メカニズムは問題の異なる部分を解決します。
責任あるレジストリは、一つのスイッチですべてのケースに対応できるふりをしません。例外的な消失には削除管理、ライフサイクルコミュニケーションには非推奨化、正当な継承には移管プロセス、アイデンティティの安全性には名前空間予約を使用します。left-pad インシデントは、古い設計が一つの公開取り消しアクションからあまりにも多くの結果を許したため、これらのメカニズムを可視化しました。
メンテナーの自律性はインフラ依存を乗り越えなければならない
厳格な不変性を支持する最も強い主張は、最も危険でもあります。一度他の人々がパッケージに依存すれば、作者は二度とそれを削除できないべきだというものです。その立場はビルドを保護しますが、共有行為を永久徴兵に変える可能性があります。ボランティアのメンテナーは、コードを公開レジストリに公開しただけでインフラ契約に署名したわけではありません。
メンテナーは嫌がらせ、法的懸念、ライセンスの誤り、秘密の偶発的な公開、個人リスク、望まない関連付け、または単純な疲労に直面する可能性があります。一部の理由は緊急の介入を必要とします。常にダウンストリームの便宜を優先するレジストリは、公開者の正当な利益に反して、機密性の高いまたは有害な資料を保存する可能性があります。継続性だけが唯一の価値であってはなりません。
答えは、労働の制御と歴史的可用性の制御を分離することです。メンテナーは作業を停止し、将来のサポート期待を拒否し、パッケージを非推奨化し、安全な条件で移管し、例外的な削除をレジストリに依頼することができるべきです。プラットフォームは、作者がメンテナンスを続けなければならないと主張することなく、既に公開されたアーティファクトを保存できます。
その区別にはユーザーへの正直なコミュニケーションが必要です。レジストリの可用性はアクティブなサポートの証明ではありません。再現可能なビルドには放棄されたコードが含まれている可能性があります。非推奨化通知は、直接的および推移的なワークフローで可視であるべきです。パッケージメタデータは、レジストリやメンテナーが行っていない保証を示唆することなく、ユーザーが所有権とライフサイクルの状態を特定するのに役立つべきです。
例外的な削除も可能であり続けるべきです。誤って公開された認証情報や明らかに違法な素材は、作者が単にきれいなプロフィールを好むパッケージとは異なる衡平性を提示します。サポートレビューは、すべての削除を禁止するのではなく、文脈を評価し副次的影響を減らすために存在します。削除が必要な場合、レジストリは依存関係に通知し、名前の安全性を維持し、適切な場合は理由を公開し、緊急度が許す場合は移行期間を提供できます。
公開証拠は npm のサポート決定の完全な分類を明らかにしていないため、すべてのエッジケースがどのようにバランスされているかを証明できません。しかし、無制限のボタンが不十分だった理由を示しています。影響の大きいアクションには摩擦、証拠、および人間のエスカレーション経路が必要です。なぜなら、永久的な不変性も無制限の削除もすべての正当な利害を尊重しないからです。
メンテナーの自律性はまた、歴史的記述における道徳的な行き過ぎを避けることに依存しています。Azer Koçulu の公開取り消し行為は広範な結果をもたらしましたが、ここでの情報源は悪意を確立していません。名前紛争にはプラットフォームの決定と相反する利害が関与していました。説明責任は参加者を caricature に変えることなく、システム全体の影響を特定できます。
このバランスは軟弱さではありません。それはより強力な制御設計です。自発的な労働に依存するシステムは、退出が可能で、期待が明確で、継続性が強制されたサポートを必要としない場合により耐久性があります。レジストリの仕事は、可能な限り退出を局所的にし、エコシステム全体の驚きにならないようにすることです。
ダウンストリームユーザーも再現性リスクを所有する
レジストリの説明責任は、パッケージを消費するソフトウェアチームの責任を免除するものではありません。すべての依存関係をネットワーク経由で取得するクリーンビルドは、レジストリの可用性、アーティファクトの削除、アカウントアクション、ルーティング障害にさらされます。重要なシステムを運用するチームは、ビルドに必要な外部サービスと、それらのサービスが期待されるバージョンを提供できない場合に何が起こるかを把握しているべきです。
ロックファイルは一つの制御ですが、left-pad はその限界も示しています。ロックファイルは正確なバージョンの決定を保存できますが、レジストリがアーティファクトを提供し続けることを保証しません。実際、正確なロックは欠落した座標を明示的にする可能性があります。再現性には、決定論的なメタデータと解決されたコンテンツへの耐久性のあるアクセスの両方が必要です。
キャッシュ、内部ミラー、アーティファクトリポジトリ、ベンダリングは取得依存関係を減らすことができます。それらの使用は結果に見合ったものであるべきです。小さな実験プロジェクトは公開レジストリのリスクを受け入れるかもしれません。本番デプロイメントパイプライン、規制対象製品、または緊急サービスシステムは、ビルド入力に対してより強力な管理を必要とするかもしれません。適切な基準は、再ビルドの失敗が何を中断するかに依存します。
これらの制御はそれ自体の義務を生み出します。ミラーは整合性を検証し、来歴を保存し、アクセスを制御し、セキュリティ更新を受け取らなければなりません。ベンダリングされたコードは不可視になり、古くなる可能性があります。キャッシュは削除される可能性があります。検証なしに最初にダウンロードされたものを保存するフォールバックは、可用性リスクと整合性リスクを交換する可能性があります。回復力とは、単により多くのコピーを作ることではありません。
依存関係のレビューには推移的なパッケージも含めるべきです。直接の依存関係はアプリケーションチームに見えますが、深いユーティリティはしばしば見えません。ソフトウェア構成ツールはグラフをマッピングできますが、スナップショットはチームが集中、放棄、重要度に基づいて行動する場合にのみ有用です。目標はすべての小さなパッケージを禁止することではありません。多くの重要な経路にどの小さなノードが存在するかを知ることです。
left-pad の記録は、影響を受けたすべてのプロジェクトがロックファイル、キャッシュ、ミラーを欠いていたことを確立しません。失敗したインストールから過失を推測するのは不公平でしょう。公開パッケージエコシステムはリモート解決を中心に設計されており、レジストリの可用性は合理的な運用前提でした。このインシデントは、チームがその前提をどの程度自信を持って行うべきかを変えました。
したがって、共有責任には2つの独立した主張があります。npm は、共通の依存関係ソースを管理していたため、より安全な削除ガバナンスを必要としていました。ダウンストリーム運用者は、彼らの配信システムを管理しているため、ビルド継続性計画を必要としています。どちらの主張も、互いを弱めることなく真実であり得ます。
爆発範囲チェックは削除に先行すべき
耐久性のあるガバナンスの教訓は手続き的です。レジストリは破壊的なアクションを許可する前に結果を見積もるべきです。現在の npm 基準は、公開依存関係、最近のダウンロード数、経過時間、所有権を観測可能なシグナルとして使用しています。より完全な説明責任モデルは、これらのシグナルを爆発範囲評価の開始点として扱い、重要性の完全な尺度とはしません。
公開依存関係カウントは、プライベートアプリケーション、生成されたビルド、リストされていないツール、中間パッケージの背後に隠れた依存関係を見逃す可能性があります。ダウンロード数には、自動化、ミラー、繰り返しインストール、ノイズが含まれる可能性があります。低ボリュームが低い結果を意味するわけではありません。一つの依存関係が重要なシステムを運用している場合。高ボリュームは、消費者が回復力のあるミラーを持っているかどうかを明らかにしません。メトリクスは判断に情報を提供しますが、それを置き換えるものではありません。
グラフ上の位置は文脈を追加できます。直接の依存関係が少ないパッケージでも、広く使われているフレームワークの下に位置する可能性があります。現在のダウンロード数が控えめなバージョンでも、古いサポートリリースを再現するために必要かもしれません。単一のアカウント下の複数のパッケージは、それぞれが単独では小さく見えても、相関した削除リスクを共有する可能性があります。2016年のイベントは、アカウントレベルのアクションが単一のパッケージ統計と同じくらい重要であり得ることを示しました。
防御可能な削除前プロセスは、何が削除されるのか、なぜか、どのバージョンが影響を受けるか、公開依存関係が存在するか、プライベートな影響を知らせることができるか、セキュリティまたはプライバシーの緊急事態が迅速さを必要とするか、非推奨化が公開者の目標を達成できるか、移管が適切か、名前空間がどのように保護されるか、どのような通知が提供できるかを問うべきです。その答えによって、アクションが自動的か、遅延か、レビューされるか、拒否されるかが決まります。
プロセスはまた、可逆性を区別するべきです。非推奨化は容易に可逆的です。所有権の移管は協力があった場合のみ可逆的かもしれません。完全な公開取り消しは即座にビルドを壊し、再公開に制約を生む可能性があります。影響が大きく、元に戻しにくいアクションは、警告メッセージよりも強力な確認とログ記録に値します。
サポート介入は説明責任の記録を作成します。リクエスト、依存関係の証拠、決定、緩和策、コミュニケーション計画を文書化できます。公開開示にはプライバシーまたはセキュリティ上の制限が必要かもしれませんが、レジストリはなぜ例外的な削除が許可されたかを後で説明するのに十分な証拠を保持すべきです。
公開ポリシーがすべての混乱を排除できるわけではありません。裁判所命令、認証情報漏洩、危険なアーティファクトは、依存関係の破損にもかかわらず緊急行動を必要とする場合があります。説明責任はゼロ障害の保証ではありません。プラットフォームが競合する害を特定し、比例した対応を選択し、回避できなかった害に対する回復を準備したという証拠です。
対応の質にはターボールの復元以上のものが必要
npm による left-pad 0.0.3 の復元は、固定されたチェーンが期待する座標を取得できるようにしたため、当面の解決失敗に対処しました。それは必要なインシデント対応でした。耐久性のある回復にはさらに多くのことが必要でした。何が起こったかを説明し、名前空間リスクを封じ込め、公開取り消しルールを変更し、将来のメンテナーに消失に代わる選択肢を提供することです。
監視も重要でした。npm による毎分数百の障害の観測は、一つのレジストリ変更が広く伝播しているというサービス側のシグナルを提供しました。成熟したレジストリは、そのような異常を最近の破壊的行動に結び付け、運用者が迅速に原因を特定できるようにすべきです。障害率検出は価値がありますが、ユーザーが警報になる前に回避可能な混乱を止められるため、事前の依存関係分析の方が優れています。
コミュニケーションは確認された事実と推定値を分離すべきです。npm はパッケージのアクション、観測された障害率、復旧時間、ポリシー変更を述べることができました。それらのシグナルから影響を受けたビルドの正確な数を導き出すことはできませんでした。当時の報道は広範なエコシステムの反応を捉えていましたが、見出しは監査された影響測定ではありません。
回復の検証は、元の座標が解決されるか、依存するインストールが成功するか、キャッシュとミラーが収束するか、名前が保護されたままか、ポリシー執行が同じ経路をブロックするようになったかを問うべきです。無制限の削除を閉じずに可用性を復元することは緩和策です。ビルドの回復を確認せずにルールを変更することは、サービス復旧のないガバナンスです。両方が必要でした。
対応はまた、整合性を弱めてはなりませんでした。迅速に公開された 1.0.0 は古いバージョンチェーンを満たさず、任意の置換を受け入れることは安全ではなかったでしょう。元の座標を復元することで、ダウンストリームメタデータによって期待される同一性が保存されました。プレースホルダーポリシーは、完全に空になった名前で何が起こり得るかに対処しました。可用性と整合性は一緒に回復され、軽率に交換されることはありませんでした。
事実、推論、未知の部分は分離されなければならない
いくつかの事実は十分に裏付けられています。kikの名前紛争が削除に先行しました。Azer Koçulu はkikとその他272のパッケージを公開取り消ししました。left-pad はその中に含まれていました。npm は太平洋時間午後2時30分頃以降、毎分数百の障害を観測しました。代替の 1.0.0 が迅速に登場しましたが、0.0.3 に固定されたチェーンを満たしませんでした。npm は午後4時55分までに 0.0.3 を復元し、約2時間半の中断があったと説明しました。その後 npm は公開取り消しポリシーを変更しました。
その他の結論は証拠に基づく推論です。レジストリは、その可用性の決定が自動解決を制御していたため、運用ビルドインフラになっていました。無制限の削除は継続性の外部性を生み出しました。依存関係のトポロジーは、コードサイズではなく、なぜ小さなパッケージが広範な影響を持つかを説明します。削除ポリシー、名前空間の安全性、非推奨化は一つのガバナンスシステムの一部です。
重要な量は不明のままです。記録は失敗したビルド、影響を受けた開発者、中断されたデプロイメント、エンドユーザーの正確な数を確立していません。「毎分数百の障害」は数百の固有の組織と同じではありません。失敗した試行は再試行される可能性があります。一つの組織が多くの試行を生成する可能性があります。一部の依存プロジェクトはそのウィンドウ中にビルドしなかったかもしれません。
記録はまた、経済的損失を確立していません。開発者時間、リリースの遅延、サポート負担、運用中断は妥当なカテゴリですが、情報源はそれらを定量化していません。金銭的見積もりにはここに存在しない証拠が必要です。
名前紛争は限定されたままです。これらの資料は法的商標問題を決定したり、いずれかの参加者が法的責任を負うことを確立したりしません。悪意を証明しません。このイベントは、アクターの制御が可視であるため、運用上の責任の割り当てをサポートします。法廷の結論をサポートするものではありません。
後のパッケージページ、バージョン一覧、リポジトリ、1.1.3 リリース記録は、継続する公開オブジェクトとその後の履歴を示しています。それらは停止状態の正確な証拠として過去に投影されるべきではありません。Azer Koçulu に関連するリポジトリは歴史的なコード系統を固定するのに役立ちます。後のメンテナンスサーフェスは継続性を示すのに役立ちます。どちらも npm の同時代のクロノロジーに代わるものではありません。
3つの現代のメディアレポートは、インシデントがどれほど迅速にエコシステムの話になり、観測者が小さなコードのパラドックスをどのように枠付けたかの有用な文脈です。それらは npm のポリシー主張を管理しません。歴史的および現在の npm ポリシーは npm 自身の投稿とドキュメントから述べられるべきであり、メディアはプラットフォームルールの権威ではなく独立した反応に使用されるべきです。
この証拠上の規律が重要なのは、left-pad がフォークロアになったからです。記憶に残る話は丸められた数字、普遍的な主張、道徳的な悪者、単純化された教訓を獲得します。責任ある説明は、正確さを犠牲にして逸話を美化することなく、インシデントを重要にしたものを保存します。
レジストリの説明責任が今示すべきこと
第一に、破壊的なパッケージアクションはダウンストリームの結果によって分類されるべきです。レジストリは、コマンドが一つの最近のバージョン、すべてのバージョン、アカウント全体、または公開依存関係のある名前空間に影響するかを知るべきです。許可と確認は範囲に応じて高まるべきです。
第二に、依存関係と使用状況の証拠は行動の前に可視であるべきです。現在の npm 基準は、依存関係、ダウンロード数、所有権、経過時間の条件を通じて公開ベースラインを提供します。運用者はまた、可能な場合、相関するアカウントレベルの変更や推移的グラフの集中を監視すべきです。
第三に、メンテナーには明確な出口の階段が必要です。継続的なメンテナンス、移管、非推奨化、アーカイブステータス、サポートレビューによる削除、緊急削除は明確な選択肢であるべきです。それぞれがアーティファクト、名前、依存関係解決、ユーザーメッセージに何が起こるかを説明すべきです。
第四に、影響の大きい削除には可用性と整合性への二重の注意が必要です。アーティファクトの保存はビルドを保護できます。名前の予約は敵対的な置換を防ぐことができます。来歴の検証は、復元が互換性のある動作を持つ何かではなく、期待されるオブジェクトを返すことを保証できます。
第五に、レジストリには観測可能なインシデントトリガーが必要です。公開取り消し活動に続く Not Found または解決失敗の急増は、迅速に運用者に届くべきです。アクションログ、依存関係グラフ、サービスメトリクスは、公衆の怒りを待たずに相互に関連付け可能であるべきです。
第六に、回復目標はバージョン固有であるべきです。古い制約がグラフに残っている場合、新しいリリースの出現だけでは十分ではありません。運用者は、どの座標が失敗し、どれが復元され、どの依存関係パスがまだ解決できないかを知る必要があります。
第七に、ポリシーの履歴は読み取り可能であるべきです。2016年の24時間ルールと現在の72時間基準は、異なる時期に異なる質問に答えます。明確なバージョン管理されたドキュメントは、古い投稿が偶発的に現在のガイダンスになるのを防ぎます。
第八に、例外レビューには証拠と抑制が必要です。一部の削除は公開者またはユーザーをより大きな害から保護します。レジストリは理由を記録し、依存関係を評価し、最も破壊的でない効果的な救済策を選択し、機密詳細を保護し、ダウンストリーム運用者が知る必要があることを伝達すべきです。
第九に、ダウンストリーム組織はクリーンルーム再ビルドをテストし、どのアーティファクトを管理しているかを把握すべきです。すべての外部レジストリオブジェクトがオンラインである間だけ成功するパイプラインは、それがサポートするサービスに見合った依存関係を運びます。
最後に、説明責任はコミュニティ価値の宣言ではなく、実証可能な制御を通じて測定されるべきです。有用な証拠は、プラットフォームが不適格な公開取り消しをブロックし、例外をレビューに回し、名前空間を安全に予約し、非推奨化警告を表示し、解決失敗を検出し、正当化された場合は正確なバージョンを復元し、執行と一致する現在のルールを公開するかどうかです。
これらの要件は、npm が今日あらゆる制御を欠いているという所見ではありません。現在のドキュメントは、インシデント前のモデルとは異なる substantial なポリシー機構を示しています。執行、サポート決定、プライベート依存関係の影響の完全な評価には、公開ページを超えた運用証拠が必要です。インシデントはテストを提供し、永続的な評決を提供するものではありません。
退出する権利には継続性の境界が必要
left-pad が警告として持続したのは、それが自動的に適合しない2つの正当な原則を結びつけたからです。作者は無限の無償メンテナンスを強制されるべきではありません。共有レジストリは、個人の退出がレビューなしに遠方のビルドシステムを無効にすることを許すべきではありません。どちらかの原則を絶対的なものとして扱うと、不公平なシステムが生まれます。
2016年の混乱は、その境界を可視化しました。kikとその他272のパッケージの削除は依存関係チェーンを通じて伝播しました。毎分数百の障害が npm のテレメトリーに現れました。新しいメジャーバージョンでの迅速な代替は、0.0.3 に固定されたチェーンを満たせませんでした。npm は期待されるバージョンを復元し、公開取り消しポリシーの失敗を認め、ルールを変更しました。
ポリシーの物語はそこで止まりませんでした。即時の24時間枠組みは歴史的なものになり、現在の npm ドキュメントは原則として公開依存関係がないことを条件に72時間のウィンドウを使用し、古いパッケージにはさらなる制限を課しています。非推奨化は明確な中間経路を提供します。取得を破壊することなく承認またはサポートを撤回します。
その進化は制度的説明責任です。痛みを伴う出来事を将来の権力に対する制約に変換します。削除ボタンは管理されたアクションになります。依存関係データは許可への入力になります。サポートは例外経路になります。名前空間予約、移管、非推奨化は即興の反応ではなく、明確なツールになります。
いかなるルールもパブリックパッケージエコシステムをリスクフリーにすることはできません。メンテナーは去ることができます。アーティファクトには深刻な欠陥が含まれる可能性があります。レジストリは失敗する可能性があります。ダウンストリームチームは再現性を無視する可能性があります。紛争は介入を必要とする可能性があります。現実的な目標は、プラットフォームがそれを封じ込めるのに十分な情報と制御を持っている場合に、一方の当事者の局所的な決定が不可視の外部性になるのを防ぐことです。
これがこのケースにおけるサプライチェーン責任の意味です。それは裁判所によって下された判断ではありません。それは、サービスが依存エコシステムの名前、アーティファクト、権限、ポリシー、復旧を集中させる時に従う責任です。npm のネットワーク効果は公開を容易にし、再利用を強力にしました。また、削除を重大なものにしました。
永続的な教訓は、開発者が小さなパッケージを信頼しないか、すべてのユーティリティを書き換えるべきだということではありません。重要度は行数ではなくグラフに存在し、プライベートアーティファクトがパブリック依存関係になった時点で、自律性には継続性の境界が必要だということです。レジストリは、メンテナーの停止する権利と、ダウンストリームユーザーの昨日のビルド入力が比例したレビューなしに消えないという合理的な期待の両方を保護できるときに、制度的正当性を獲得します。
出典
- https://blog.npmjs.org/post/141577284765/kik-left-pad-and-npm
- https://blog.npmjs.org/post/141905368000/changes-to-npms-unpublish-policy
- https://blog.npmjs.org/post/141985926180/on-dependecy-squatter-packages.html
- https://docs.npmjs.com/policies/unpublish/
- https://docs.npmjs.com/unpublishing-packages-from-the-registry/
- https://docs.npmjs.com/deprecating-and-undeprecating-packages-or-package-versions/
- https://docs.npmjs.com/policies/
- https://www.npmjs.com/package/left-pad
- https://www.npmjs.com/package/left-pad?activeTab=versions
- https://github.com/stevemao/left-pad
- https://github.com/stevemao/left-pad/releases/tag/1.1.3
- https://github.com/azer/left-pad
- https://github.com/npm/documentation/blob/main/content/policies/unpublish.mdx
- https://github.com/npm/documentation/blob/main/content/packages-and-modules/removing-a-package-from-the-registry/unpublishing-packages-from-the-registry.mdx
- https://qz.com/646467/how-one-programmer-broke-the-internet-by-deleting-a-tiny-piece-of-code
- https://www.theregister.com/2016/03/23/npm_left_pad_chaos/
- https://www.infoworld.com/article/2268405/how-one-developer-just-broke-node-babel-and-thousands-of-projects-in-11-lines-of-javascript.html

