---
title: "Composer 2.11: cooldown для нових версій пакетів і виправлення безпеки"
url: https://laravelukraine.com/blog/composer-211-cooldown-dlia-novix-versii-paketiv-i-vipravlennia-bezpeki
date: 2026-10-31
---

# Composer 2.11: cooldown для нових версій пакетів і виправлення безпеки

29 жовтня вийшов [Composer 2.11.0](https://github.com/composer/composer/releases/tag/2.11.0), а наступного дня - [2.11.1](https://github.com/composer/composer/releases/tag/2.11.1) з першими виправленнями. Головна новинка - політика cooldown: Composer може притримувати щойно опубліковані версії пакетів, доки не мине заданий час. Для будь-якого Laravel-проєкту це найдешевший захист від атак на ланцюжок постачання, який можна увімкнути одним рядком у `composer.json`.

### Навіщо затримка

Як пише Нільс Адерман в [анонсі випуску](https://blog.packagist.com/composer-2-11-release/), більшість шкідливих версій, які за останні місяці з'являлися на Packagist.org, опублікували зловмисники, що ненадовго отримали контроль над легітимним пакетом, наприклад через зламаний акаунт GitHub. Політика malware з Composer 2.10 блокує таку версію, щойно її позначили, але між публікацією і позначкою завжди є вікно. Якщо в цей момент хтось запускає `composer update`, шкідливий код потрапляє в `composer.lock`.

Cooldown (його ще називають мінімальним віком випуску) це вікно звужує. Автоматичні сканери ловлять перші проблеми за лічені хвилини, тож навіть година затримки дає їм шанс. Звіти, які потребують ручної перевірки, йдуть довше, і для них автори радять від кількох годин до доби. Гарантії немає, але кожна година затримки підвищує шанс, що шкідливу версію позначать раніше, ніж вона дійде до вас.

Минулого разу ми писали про [Laravel Vet](https://laravelukraine.com/blog/laravel-vet-peregliad-kodu-composer-paketiv-pered-vstanovlenniam), який показує зміни в коді пакетів перед оновленням. Cooldown його доповнює: Vet - це перегляд коду, cooldown - часова затримка, і одне не замінює іншого.

### Як увімкнути

Політика налаштовується в `config.policy`, як і інші політики залежностей, і за замовчуванням вимкнена:

```json
{
  "config": {
    "policy": {
      "cooldown": {
        "period": "1 day",
        "ignore": {
          "mycompany/*": "We trust the code in our own packages"
        }
      }
    }
  }
}
```

- `period` приймає рядок на кшталт `"6 hours"` з одиницями `second`, `minute`, `hour`, `day`, `week` або ціле число секунд;
- `ignore` назавжди виключає пакети з-під затримки, підтримує пояснення, обмеження версій і wildcard - зручно для власних пакетів компанії;
- ту саму настройку можна прописати в глобальній конфігурації Composer або задати змінною `COMPOSER_POLICY_COOLDOWN_PERIOD`, наприклад у CI.

### Як cooldown поводиться в командах

- Політика діє, коли Composer розв'язує залежності, тобто на `update` і `require`. `composer install` і далі ставить рівно те, що лежить у `composer.lock`.
- `require`, `init` і `create-project` пропускають притримані версії, коли обирають версію пакета.
- `outdated` і `show --latest` показують найновішу дозволену версію і окремо згадують випуски, що ще чекають.
- Dev-версії на кшталт `dev-main` і платформні пакети ніколи не притримуються.
- Частковий `composer update vendor/package` не чіпає інших заблокованих пакетів. А от повний `composer update` переоцінює все, тож якщо в lock-файлі вже є версія, яка ще в cooldown, Composer може замінити її старішою.

### Виправлення безпеки теж чекатимуть

Затримка стосується кожної нової версії, включно з тими, що закривають вразливості. Автоматично пропускати їх Composer не може: зловмисник із доступом до репозиторію пакета має ті самі права, що й мейнтейнер, і сам опублікує advisory, щоб обійти затримку.

Тому рішення лишається за вами. Щоб поставити виправлення одразу, є нова опція `--no-cooldown` для `update`, `require`, `remove` і `create-project`:

```bash
composer update --no-cooldown vendor/package
```

Вона вимикає лише cooldown. Блокування версій з відомими вразливостями, malware і ваші власні політики працюють і далі.

Звідси практичний висновок: що довша затримка, то довше до вас ідуть виправлення вразливостей, яких ви не відстежуєте вручну. Кілька годин або доба - розумний компроміс.

### Звідки Composer знає час публікації

Cooldown не з'явився ще в 2.10, бо в метаданих не було надійної дати. Поле `time` Packagist.org бере з дати коміту тега або з `composer.json` пакета, тобто його контролює той, хто публікує. Зловмисник може «зістарити» шкідливу версію на кілька тижнів, і затримка за полем `time` пропустить її одразу.

Тепер Packagist.org віддає для кожної версії `published-time` - момент, коли він сам уперше зробив версію доступною ([composer/packagist#1765](https://github.com/composer/packagist/pull/1765)). Якщо інший репозиторій такого поля не віддає, команда падає і називає пакет, тож відсутня позначка часу ніколи тихо не вимикає захист. Для репозиторіїв, яким ви довіряєте, можна поставити `require-published-time` у `false` і повернутися до поля `time`. VCS-, path- і artifact-репозиторії мають лише `time`. Усі деталі - в [документації конфігурації](https://getcomposer.org/doc/06-config.md#cooldown).

### Виправлення безпеки

У 2.11.0 закрито кілька проблем:

- [GHSA-c968-33g3-wh7p](https://github.com/composer/composer/security/advisories/GHSA-c968-33g3-wh7p): імена пакетів у `vendor/composer/installed.json` могли вивести запис за межі каталогу `vendor` під час встановлення і перевстановлення;
- [GHSA-fm2w-xgf2-f9fh](https://github.com/composer/composer/security/advisories/GHSA-fm2w-xgf2-f9fh): HTTP-заголовки, прописані прямо в конфігурації репозиторію (наприклад, API-токени), записувалися в `composer.lock` і `installed.json`;
- TLS-з'єднання з недовіреними скомпрометованими проміжними сертифікатами eMudhra тепер відхиляються, навіть якщо системне сховище CA довіряє їхнім кореневим;
- додаткові аргументи `@composer`-скриптів тепер екрануються;
- bin-проксі більше не вбудовують шляхи і shebang з пакета без екранування, а шляхи з метасимволами оболонки відхиляються;
- `secure-http` ловить і некоректні URL, і URL із синтаксисом `<transport>::<address>`;
- власні HTTP-заголовки репозиторію більше не надсилаються на dist-адреси інших хостів, чиє ім'я лише починається так само.

Друга вразливість вимагає дії, а не лише оновлення. Якщо ви коли-небудь прописували токен у `headers` репозиторію в `composer.json`, перевірте вже закомічені `composer.lock`: оновлений Composer не прибере з історії git те, що туди вже потрапило. Знайшли токен - відкличте його і випустіть новий. Надалі облікові дані краще тримати в `auth.json` або `COMPOSER_AUTH`.

Ті самі виправлення отримала гілка LTS: [Composer 2.2.31](https://github.com/composer/composer/releases/tag/2.2.31) для проєктів, які досі живуть на старому PHP.

### Що може зламатися в CI

- **Немає переходу з dist на source.** Composer 2.10 оголосив його застарілим і залишив тимчасову опцію `source-fallback`; у 2.11 її прибрали. Якщо dist-архів не завантажився, встановлення падає замість тихого `git clone`. Source можна попросити явно через `preferred-install` або `--prefer-source`.
- **Конфлікт злиття в `content-hash`.** `composer install` тепер падає, якщо в `composer.lock` лишився нерозв'язаний конфлікт у `content-hash`.
- **Lock-файл застаріває від `policy`.** Зміни `config.policy` тепер позначають lock-файл застарілим. Якщо у проєкті є такий конфіг, після оновлення ви побачите попередження, доки не оновите lock-файл. Зробіть це окремим комітом.
- **Власні політики можуть блокувати `install`.** Нова опція `block-scope: all` для власних політик блокує відповідні версії і під час `install`, тож версія, додана до вашого списку після створення lock-файлу, зупинить наступне встановлення.

### Інше у випуску

- швидше розв'язання залежностей і менше пам'яті;
- `composer audit --direct` (`-D`) перевіряє лише прямі залежності;
- `outdated` і `show --latest` завантажують метадані паралельно;
- на відповідь 429 із `Retry-After` Composer чекає і повторює запит;
- Composer більше не запитує HTTP/3, який додавав затримку до кожного нового з'єднання з новими версіями curl;
- нова опція `only-branches` для VCS-репозиторіїв і конфіг `strict-psr-autoloader`.

Composer 2.11.1 виправляє автентифікацію через GitLab CI job token у реєстрі пакетів GitLab, попередження PHP 8.6 про депрекейт з `composer/ca-bundle` і падіння кожного `update` із `SecurityException`, коли розширення PHP має невалідне ім'я платформного пакета.

### Що зробити

Оновіться і на локальній машині, і в CI-образах:

```bash
composer self-update
```

Далі - три кроки. Перевірте історію `composer.lock` на токени, якщо колись прописували їх у `headers`. Прогоніть CI і подивіться, чи не тримався він на переході з dist на source. І додайте `"cooldown": {"period": "1 day"}` хоча б у проєкти, де `composer update` запускає бот: саме автоматичні оновлення найчастіше підтягують шкідливу версію в перші години.
