パッケージマネージャーは冷静になる必要がある
Andrej Karpathyは、Seth Larsonからの依頼を受け、依存関係の「クールダウン」機能(新バージョン公開後一定期間インストールを制限するセキュリティ対策)が各パッケージマネージャーでどのように実装されているか、およびその現状と課題を詳細に分析している。
キーポイント
依存関係クールダウンの基本概念と必要性
William Woodruffが提唱したこの概念は、ハッカーがメンテナンス権限を奪取または取得した後、悪意のあるバージョンを公開して自動ツールで数千のプロジェクトに取り込まれるまでの時間的猶予を与えるものであり、7日間のクールダウンで大半のサプライチェーン攻撃を阻止可能だとする。
主要エコシステムにおける実装状況の格差
JavaScriptエコシステム(pnpm, npmなど)は先行して実装を進めている一方、Ruby/BundlerやRust/Cargo, Goなどはネイティブサポートが欠如しており、コミュニティ製ツールやCIパイプラインでの対応に頼らざるを得ない状況にある。
インフラレベルとクライアントレベルのアプローチ対比
gem.coopのようなコミュニティサーバーがインフラ側でクールダウンを強制するアプローチを示す一方、多くの言語ではクライアント側の設定やサードパーティ製ラッパーに依存しており、開発者個人の環境での手動更新(例: cargo update)に対する保護が不完全である。
自動化ツールと設定チェックの役割
RenovateやDependabotといった依存関係更新ツールは既にこの機能に対応しているが、zizmorのような設定検証ツールも追加されており、セキュリティポリシーの遵守を支援するエコシステムが形成されつつある。
影響分析・編集コメントを表示
影響分析
この記事は、現代のソフトウェア開発において不可欠となったサプライチェーンセキュリティ対策の実装ギャップを浮き彫りにしています。特に、JavaScriptエコシステム以外の主要言語(Rust, Go, Rubyなど)がセキュリティ標準において遅れを取っている現状を指摘しており、開発者や組織に対して、単なる自動化ツールの設定だけでなく、レジストリレベルのセキュリティポリシーやネイティブツール機能の活用を促す重要な示唆を提供しています。
編集コメント
Karpathyの分析は、セキュリティ対策が「ツール間の競争」によって急速に普及する可能性を示唆していますが、標準化されていない現状は運用上の混乱を招くリスクもあります。組織レベルでは、使用している言語エコシステムに合わせた具体的なクールダウンポリシーの策定が急務です。
この投稿は、Seth Larsonからのリクエストに応じたものです。彼は、各種パッケージマネージャーにおける依存関係クールダウンの比較分析を依頼しました。彼の主張は次の通りです:すべてのツールは、グローバルに設定可能な exclude-newer-than=<相対期間> をサポートすべきである。
攻撃者がメンテナの認証情報を侵害したり、休眠中のパッケージを乗っ取ったりした場合、彼らは悪意のあるバージョンを公開し、自動化ツールがそれを何千ものプロジェクトに取り込むのを、誰にも気付かれる前に待ちます。William Woodruffは2025年11月に依存関係クールダウンの必要性を提唱し、その1か月後に改めて主張しました。すなわち、パッケージのバージョンは、レジストリに公開されてから一定の最低期間が経過するまでインストールすべきではない、と。これにより、自らのビルドが問題のあるパッケージを取り込む前に、コミュニティやセキュリティベンダーが問題を発見する時間を確保できます。彼が調査した10件のサプライチェーン攻撃のうち、8件は攻撃可能な期間(ウィンドウ)が1週間未満でした。したがって、たとえ7日間という控えめなクールダウンでも、それらの大半がエンドユーザーに到達するのを阻止できたでしょう。
この概念はツールによって呼称が異なります(クールダウン、minimumReleaseAge、minimumReleaseAgeExclude、npmMinimalAgeGate、npmPreapprovedPackages、minimumReleaseAge、min-release-age、--minimum-dependency-age)。
JavaScriptエコシステムは他に先駆けてこの機能に対応し、pnpmが minimumReleaseAge を実装しました。uvは --exclude-newer、exclude-newer-package、--uploaded-prior-to を備えています。
BundlerとRubyGemsにはネイティブのクールダウンサポートはありませんが、コミュニティ運営のgemサーバーであるgem.coopがクールダウンのベータ版を開始し、新規公開されたgemを別のエンドポイントから提供する際に48時間の遅延を強制しています。クールダウンをクライアント側ではなくインデックス(サーバー)レベルで実施するのは興味深いアプローチです。なぜなら、gem.coopエンドポイントを参照するように設定したBundlerユーザーは、ツールやワークフローを一切変更することなく、クールダウンの恩恵を受けられるからです。
Rust、Go、PHP、.NET
これらのエコシステムはまだ議論の段階にあります。Cargoには未解決のイシューが存在し、当面の間、概念実証として開発者マシン上で設定可能なクールダウン期間を強制するサードパーティのラッパーである cargo-cooldown が利用できます(CIパイプラインでは、コミット済みのロックファイルに対しては従来通りプレーンなCargoを使用し続けることが想定されています)。Goには go get に関する公開提案があります。
依存関係更新ツール
Renovateは minimumReleaseAge、security:minimumReleaseAgeNpm、semver-major-days、semver-minor-days、semver-patch-days をサポートしています。
設定の確認
zizmorは dependabot-cooldown、AddDependabotCooldown、--cooldown-days を追加しました。
Cargo、Go、Bundler、Composer、pipはまだネイティブのクールダウンサポートを有していません。これは、更新の遅延を実施するためにDependabotやRenovateに依存する必要があることを意味します。これらは自動更新をカバーしますが、誰かが手動で cargo update を実行するのを阻止するものではありません。
原文を表示
This post was requested by Seth Larson, who asked if I could do a breakdown of dependency cooldowns across package managers. His framing: all tools should support a globally-configurable exclude-newer-than=<relative duration>
When an attacker compromises a maintainer’s credentials or takes over a dormant package, they publish a malicious version and wait for automated tooling to pull it into thousands of projects before anyone notices. William Woodruff made the case for dependency cooldowns in November 2025, then followed up with a redux a month later: don’t install a package version until it’s been on the registry for some minimum period, giving the community and security vendors time to flag problems before your build pulls them in. Of the ten supply chain attacks he examined, eight had windows of opportunity under a week, so even a modest cooldown of seven days would have blocked most of them from reaching end users.
The concept goes by different names depending on the tool (cooldown
minimumReleaseAge
The JavaScript ecosystem moved on this faster than anyone else, with pnpm shipping minimumReleaseAge
minimumReleaseAgeExclude
npmMinimalAgeGate
npmPreapprovedPackages
minimumReleaseAge
min-release-age
--minimum-dependency-age
uv has had --exclude-newer
exclude-newer-package
--uploaded-prior-to
Bundler and RubyGems have no native cooldown support, but gem.coop, a community-run gem server, launched a cooldowns beta that enforces a 48-hour delay on newly published gems served from a separate endpoint. Pushing the cooldown to the index level rather than the client is interesting because any Bundler user pointed at the gem.coop endpoint gets cooldowns without changing their tooling or workflow at all.
Rust, Go, PHP, .NET
These ecosystems are still in the discussion phase. Cargo has an open issue, and in the meantime there’s cargo-cooldown, a third-party wrapper that enforces a configurable cooldown window on developer machines as a proof-of-concept (CI pipelines are expected to keep using plain Cargo against committed lockfiles). Go has an open proposal for go get
Dependency update tools
Renovate has had minimumReleaseAge
security:minimumReleaseAgeNpm
semver-major-days
semver-minor-days
semver-patch-days
Checking your config
zizmor added a dependabot-cooldown
AddDependabotCooldown
--cooldown-days
Cargo, Go, Bundler, Composer, and pip don’t have native cooldown support yet, which means you’re relying on Dependabot or Renovate to enforce the delay. That covers automated updates, but nothing stops someone from running cargo update
minimumReleaseAge
min-release-age
npmMinimalAgeGate
uploaded-prior-to
minimum-dependency-age
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み