テック技報最新号へ →
セキュリティ

Composer 2.11 の cooldown は「1 日前後」から始める(7 日だと脆弱性ブロックと挟み撃ちで update が止まる)

Composer 2.11 で入った「公開直後の版を一定期間入れない」cooldown を 7 日にすると、既定で有効な既知脆弱性ブロックと組み合わさって、修正版が出た直後に依存解決が不能になる。普段は 1 日前後、7 日待ちたいなら更新 PR 側で待つ二段構えにする。

@superdoccimo · 2026-10-31
#supply-chain#composer#php#cooldown#dependency-management

何が起きるか

  • Composer 2.10 から、既知の脆弱性がある版は既定でインストール候補から外される。
  • 2.11 の cooldown は、Packagist に出てから設定期間が過ぎていない版を隠す。セキュリティ修正版も例外にしない(乗っ取ったパッケージの攻撃者が自分で「アドバイザリー」を出して素通りさせる抜け道を塞ぐため)。
  • その結果、ある依存(報告例では Laravel が必須にしている symfony/mime、CVE-2026-45070)で修正版が出ると、古い版は脆弱性で拒否、新しい版は cooldown で拒否となり、composer update が終了コード 2 で失敗する。
  • 投稿者の検証では、1 日と 36 時間は成功、40 時間・2 日・7 日・30 日は失敗。境目は修正版の公開からの経過時間(約 39.6 時間)と一致した。7 日設定だと、この状態が数日続く。
  • 失敗するのは依存を解決し直す update と require だけ。composer install はロックファイルどおりに入れるので、7 日設定でも通る。

推奨する運用

  1. cooldown は数時間〜1 日程度から始める(公式ブログの推奨も「数時間から 1 日」)。設定ドキュメントの例が 7 days でも、npm の min-release-age=7 や Dependabot の 7 日をそのまま横展開しない。
  2. 7 日待ちたい場合は、Composer 側は 1 日にしておき、Dependabot などの更新 PR 側で 7 日待つ二段構えにする。
  3. CI で composer update を自動実行しているなら、解決失敗を「cooldown と脆弱性ブロックの衝突」として検知できるようにし、該当パッケージだけ人が判断して上げる手順を決めておく。
    • 全体を一時的に外す: composer update --no-cooldown
    • パッケージ単位で除外する ignore 設定を使う
  4. 社内ミラーや Satis など、published-time を出せないリポジトリでは cooldown が当てにならないことを把握しておく(次節)。

published-time と time の違い

  • 従来 Packagist のメタデータにあった time は、タグのコミット日時か composer.json に書かれた値で、公開時刻ではない。投稿者の集計では、2026 年に Packagist へ出た正式版 3,230 件のうち 57% が、公開の瞬間に time が 24 時間以上前だった(Laravel から分割配布される illuminate/* など)。time 基準の待機は、悪意がなくても過半数の新版を素通りさせる。
  • Packagist は今回から、自分が最初に配信した時刻を published-time として全バージョンに付けている。2.11 の cooldown はこれを使う。
  • published-time がないリポジトリでは、Composer は「新旧を判断できない」としてパッケージ名を挙げて停止する。require-published-time を false にすると警告付きで time を信じるため、time を 2020 年に偽装した作りたての版がそのままロックされた(投稿者の検証)。この設定を緩めるのは、偽装の余地を理解したうえで。

注意点

出典

X の元の投稿を開く