Composer 2.11.0 has a new cooldown dependency policy. You set a waiting time, such as one day, and Composer skips any package version published more recently than that. Composer 2.10 added the first dependency policies, which block versions with security advisories or known malware.
This release also includes six security fixes and faster dependency resolution. If you still depend on Composer falling back to source installs, check the upgrade notes first, since that behavior is gone.
What's New
Cooldown Dependency Policy
Say you set a one-day cooldown, and someone publishes a malicious version of a package you depend on. Composer won't install that version for a day after it was published. If the version is reported and removed in that time, your project never installs it. The policy is off until you set a period under config.policy:
{ "config": { "policy": { "cooldown": { "period": "1 day" } } } }
The period takes a string such as "6 hours" or "7 days", using the units second, minute, hour, day, or week. It also accepts an integer number of seconds.
The policy applies when Composer resolves dependencies during composer update and composer require. The require, init, and create-project commands skip withheld versions when they pick a version constraint. composer outdated and composer show --latest report the newest version you are allowed to install and mark newer releases that are still in the cooldown period.
The cooldown does not affect composer install, which installs exactly what is in composer.lock. Dev versions such as dev-main and platform packages (PHP and extensions) are never withheld.
composer update vendor/package leaves every other locked package alone. A full composer update re-evaluates everything, and it replaces a locked version still in the cooldown period with an older release. If no older version satisfies your constraints, the update fails.
You can exempt packages with an ignore list. Entries support reasons, version constraints, and wildcards:
{ "config": { "policy": { "cooldown": { "period": "1 day", "ignore": { "mycompany/*": "We trust the code in our own packages" } } } } }
When you need a security fix right away, pass --no-cooldown to update, require, remove, or create-project. This skips only the cooldown. The advisory, malware, and custom policies still apply.
composer update --no-cooldown vendor/package
In CI, you can set or override the period with the COMPOSER_POLICY_COOLDOWN_PERIOD environment variable. Setting it to 0 turns off the cooldown for that run.
Composer 2.10 shipped without this policy because the only timestamp in package metadata was the time field, which package authors control. Packagist.org now reports a published-time for each version, based on when Packagist first made that version available. If a different Composer repository does not report published-time for a version Composer needs, the command fails and names the package. For repositories you trust, set require-published-time to false to fall back to the time field in each package's composer.json. VCS, path, and artifact repositories always use time.
Private Packagist already supports the cooldown policy. Organization admins can also set one cooldown period for every project in the organization, regardless of which Composer version each project uses.
If you used the community Heimdall plugin to set a minimum package age, Composer can now do this without a plugin.
PRs: #12692, #13098, #13099, #13100, #13102, #13153
Security Fixes
- GHSA-c968-33g3-wh7p: during install or reinstall, Composer no longer writes files outside the vendor directory when a package name in
vendor/composer/installed.jsonpoints there. - GHSA-fm2w-xgf2-f9fh: HTTP headers set on inline repositories, such as API tokens, are no longer written to
composer.lockorinstalled.json. - TLS connections that use the distrusted eMudhra intermediate certificates are rejected, even when the system CA store trusts their roots (#13146).
- Bin proxies now escape package-controlled paths and shebangs, and Composer rejects paths that contain shell metacharacters (#13056).
- The
secure-httpsetting also catches invalid URLs and git's<transport>::<address>syntax (#13144). - Repository options such as custom headers are no longer sent to dist URLs on hosts whose names only start with the repository's host name (#13142).
Custom Policy Block Scope
Custom dependency policies used to block versions only during composer update. You can now set block-scope on a custom policy to install or all to have it block during composer install as well. The default is update:
{ "config": { "policy": { "my-policy": { "block-scope": "all" } } } }
Say your policy starts blocking a version that is already in your committed lock file. With block-scope set to all, the next composer install in CI or on deploy fails instead of installing that version.
PR: #12990
Source Fallback Removed
Composer usually installs a package from its dist, a zip archive of the release. If that download fails, Composer no longer falls back to cloning the package's source repository. The temporary source-fallback option, deprecated in 2.10, is also gone. You can still install from source with the preferred-install config option (which can be set per vendor) or the --prefer-source flag.
PR: #13050
Faster Dependency Resolution
Composer now resolves dependencies faster and with less memory. The announcement doesn't include benchmarks, but #13174 measured one of the changes on laravel/laravel: CPU time for composer update --no-install dropped from 1.50 seconds to 1.18 seconds.
PRs: #13071, #13072, #13103, #13123, #13124, #13132, #13174
Other Improvements
composer audit --direct(-D) audits only your direct dependencies (#13121)outdatedandshow --latestload package metadata in parallel (#13113)- Composer no longer requests HTTP/3, which caused a delay on new connections with recent curl versions (#13096)
- Requests that return HTTP 429 with a
Retry-Afterheader are retried (#13082) composer installfails whencomposer.lockhas a merge conflict in itscontent-hash(#13105)- Conflict error messages now say when a version was blocked by a security advisory (#13108, #13075)
- VCS repositories accept an
only-branchesoption (#13086) strict-psr-autoloaderis now a config option (#12893)- Support for
ssh.bitbucket.org(#13152) - Terminal progress reporting through OSC 7501 and OSC 9 sequences, configurable with
COMPOSER_TERMINAL_STATUS(#13117)
Upgrade Notes
Upgrade with:
composer self-update
- If a package only installs correctly from source, set
preferred-installtosourcefor that package, or pass--prefer-source. - Changes to the
policyconfig now mark the lock file as outdated. Projects that have apolicyconfig will see a warning after upgrading until they update the lock file (#13149).