Composer 2.11.0 is out. Its headline feature is a cooldown policy that holds back newly published package versions for a period you choose. Nils Adermann announced the release on the Packagist blog, and the Composer team tagged it on October 29, 2026.
The main changes in this release:
- A
cooldowndependency policy that withholds new versions for a period you configure - A
--no-cooldownoption that skips the cooldown for a single run - Nine security fixes, including two GitHub Security Advisories
- Removal of the
source-fallbackconfig option that Composer 2.10 deprecated - A
block-scopeoption for custom policies, so they can block duringcomposer install - Faster dependency resolution that uses less memory
What's New
Cooldown Periods for New Releases
Packagist says most of the malicious releases it has seen on Packagist.org in recent months came from attackers who briefly took control of a legitimate package, for example through a compromised GitHub account. The malware policy from Composer 2.10 blocks a version once someone flags it. There's still a window between publication and flagging, and a cooldown keeps new versions out of your composer update during that window. Some other tools call this a minimum release age.
Automated malware scanners can flag problems within minutes of a release, so Packagist says even a one-hour cooldown gives them a chance to act. Reports that need a human take longer. Packagist suggests a period of a few hours up to a day to catch more of those. The blog post is clear that a cooldown can't guarantee a malicious release gets flagged in time.
The policy lives under config.policy with the other dependency policies, and it's off by default. Here is how you withhold every version published in the last day:
{ "config": { "policy": { "cooldown": { "period": "1 day" } } } }
period takes a string like "6 hours" with the units second, minute, hour, day, or week, or an integer number of seconds. You can also set it in your global Composer config, or with the COMPOSER_POLICY_COOLDOWN_PERIOD environment variable in CI.
The cooldown applies when Composer resolves dependencies, which means update and require. composer install still installs exactly what's in composer.lock. Here is how the other commands behave:
require,init, andcreate-projectskip withheld versions when they pick a versionoutdatedandshow --latestreport the newest version the policy allows and point out releases still in their cooldown period- Dev versions like
dev-mainand platform packages (PHP and extensions) are never withheld
A partial update such as composer update vendor/package leaves the other locked packages alone. A full composer update checks every package again. If your lock file already holds a version that's still in its cooldown period, Composer may replace it with an older release. According to the config docs, the update fails if no other version satisfies your requirements.
PRs: #12692, #13098, #13099, #13100, #13102, #13153
Security Releases and the Cooldown
The cooldown applies to every new version, and that includes security fixes. With a one-day period, Composer won't install a fix during its first day unless you tell it to.
Composer doesn't exempt security releases automatically. An attacker with access to a package's repository has the same permissions as its maintainer. They could publish a security advisory themselves, or ship a malicious version right after a real advisory goes out. Any exemption based on advisory data would give them a way around the cooldown.
To install a fix right away, pass the new --no-cooldown option to update, require, remove, or create-project:
composer update --no-cooldown vendor/package
This skips only the cooldown. Blocking for security advisories, malware, and your other policies stays on.
For packages you always want right away, such as your own, use ignore. It supports reasons, version constraints, and wildcards, like the other dependency policies:
"cooldown": { "period": "1 day", "ignore": { "mycompany/*": "We trust the code in our own packages" } }
Packagist also points out the cost of a long period. --no-cooldown only helps when you know about the vulnerability. A longer cooldown delays every fix for a vulnerability you aren't tracking.
The New published-time Field
Cooldown policies didn't ship in Composer 2.10 because the package metadata had no timestamp Composer could trust. The only date was the time field. Packagist.org takes it from the tag's commit date or from the package's composer.json, and whoever publishes the release controls both. An attacker could backdate a malicious release by a few weeks and get straight past a cooldown based on time.
Packagist.org now includes a published-time for every version. It records when Packagist.org itself first made the version available (composer/packagist#1765).
The cooldown has these limits with other repositories:
- If a Composer repository doesn't report
published-timefor a version Composer needs, the command fails and names the package. A missing timestamp never turns the cooldown off silently. - For a repository you trust, you can set
require-published-timetofalseto fall back to thetimefield. - VCS, path, and artifact repositories only have the
timefield. - The docs say a version with no publication date at all, such as an inline package without a
timefield, is let through rather than blocked forever.
Packagist's paid service, Private Packagist, already supports the cooldown policy. Organization admins can set a cooldown for every project that uses the organization's repository, whatever Composer version those projects run. The cooldown dependency policy docs cover the setup.
Security Fixes
Composer 2.11 includes nine security fixes:
- Package names in
vendor/composer/installed.jsoncan no longer escape the vendor directory during install and reinstall (GHSA-c968-33g3-wh7p) - Inline HTTP headers in a repository config, such as API tokens, are no longer written into
composer.lockorinstalled.json(GHSA-fm2w-xgf2-f9fh) - Composer rejects TLS connections that present the distrusted, compromised eMudhra intermediate certificates, even when the system CA store trusts their roots (#13146)
- Bin proxies no longer embed package-controlled bin paths and shebangs unescaped, and Composer rejects bin paths with shell metacharacters (#13056)
secure-httpnow catches insecure URLs that aren't strictly valid or that use git's<transport>::<address>syntax (#13144)- Repository options like custom HTTP headers are no longer sent to dist URLs on other hosts whose name starts with the repository host (#13142)
- Extra arguments passed to
@composerscripts are now escaped (#13169) - SVN passwords are redacted from debug output (#13171)
- Credentials embedded in URLs are removed from hg and fossil error output (#13172)
Custom Policies Can Block During Install
Custom dependency policies, such as an internal list of disallowed package versions, can now use the block-scope option that the malware policy already had. Set it to all, and a version you add to your list after the lock file was created fails the next composer install.
PR: #12990
Faster Dependency Resolution
Composer resolves dependencies faster and uses less memory in 2.11, across #13071, #13072, #13103, #13123, #13124, #13132, and #13174. The release notes don't include benchmark numbers.
A few related changes affect speed and error output:
- Composer no longer requests HTTP/3, which added a delay to every new connection with recent curl versions (#13096)
composer outdatedandcomposer show --latestload package metadata in parallel (#13113)- Dependency conflict errors explain versions blocked by security advisories more clearly (#13108, #13075)
Other Changes
composer audit --direct(-D) audits only your direct dependencies (#13121)- Composer waits and retries when a repository returns a 429 with a
Retry-Afterheader (#13082) - A new
only-branchesoption on VCS repositories limits which branches Composer loads (#13086) strict-psr-autoloaderis now available as a config option as well as a flag (#12893)- Composer supports Bitbucket Cloud's new
ssh.bitbucket.orghostname and uses it for the SSH fallback (#13152) - Composer reports progress to terminals that support OSC 7501 and OSC 9 escape sequences, configurable with
COMPOSER_TERMINAL_STATUS(#13117)
Upgrade Notes
- Source fallback is gone. Composer 2.11 removes the temporary
source-fallbackoption from 2.10. When a dist download fails, Composer no longer falls back to a source checkout. You can still install from source on purpose with thepreferred-installconfig option or--prefer-source(#13050). - Lock file warning. Composer now marks the lock file as outdated when your policy config changes, which 2.10 missed. If your project defines a policy config, you'll see a lock file warning after upgrading until you update the lock file (#13149).
- Merge conflicts in the lock file.
composer installnow fails whencomposer.lockhas acontent-hashmerge conflict (#13105). - Plugin authors: the release bumps
composer-plugin-apito 2.11.0.
To upgrade, run:
composer self-update
We covered more of the supply chain side of Composer and Packagist in Composer After the Attack: A SymfonyCon 2026 Talk, and the rest of our coverage is on the security tag.