Appearance
Composer cooldown in a Laravel project: what it protects, and the week it breaks installs
A Laravel site runs on a few hundred packages it never chose one by one. Each of them is somebody's account on Packagist or GitHub, and an account can be taken over. Whoever gets in publishes a new version, and every project that runs composer update before it is noticed installs it. What such a version does first is predictable: it reads .. On a kitloom site that file holds the database password, the application key and the keys of the payment, mail and storage services.
This has happened again and again. In September 2025 a phished maintainer put malicious versions of chalk and debug on npm, packages with billions of weekly downloads between them; the bad versions were gone within hours. PHP's ecosystem has had its own hijacked packages. The pattern is the same each time: the bad version is found fast, so the damage is done in the first hours and days.
What a cooldown does
Composer 2.11 adds a policy for exactly that window. In composer.:
json
"config": {
"policy": {
"cooldown": {
"period": "7 days"
}
}
}From then on composer update and composer require pass over every version younger than a week, and composer outdated tells you what is waiting. composer install is not touched: it installs what composer. holds, so a server that deploys a committed lock behaves as before. The protection sits where versions are chosen, on your machine.
What we turned on
kitloom is tested in two applications, one per admin, that run every package's tests together. They are also where we pick up new versions of Laravel, Filament, Symfony and the rest, so they are where a hijacked release would reach us first. Both now run with a week's cooldown. As this post is written, a full composer update there holds back 187 versions that are not a week old yet.
A cooldown needs to know when each version was published, and it has to be a time the repository vouches for. Packagist gives one for every version, published-. The package's own time won't do: it comes from git, and whoever pushes the code sets it.
Our own repository, packages.kitloom.dev, is built with Satis, which writes no published- at all. Its time was no substitute either: for kitloom's packages it is the date of the last commit to each package, so a package that did not change between three releases showed the same date for all three. So the build now stamps every release with the moment it first offered it, kept on our side between builds — the releases before that, with the date of their tag. Composer 2.11 counts from it like from Packagist's: a site with a week's cooldown and nothing ignored gets the newest kitloom release that is a week old.
Nova's repository gives no time, and for a version without one Composer stops and names the package. So Nova goes under ignore and comes in the day it is released — a trade we make knowingly. The test applications ignore kitloom's packages too: there they come from the repository they are written in, not from a download.
The week it would have broken every new site
The obvious next step was to put the same lines into the starters that laravel new -- installs from. Before shipping it, we tried a clean install with the cooldown on. It failed.
On 28 October an advisory came out for symfony/, which Laravel requires: CVE-2026-45070, an email header injection. Symfony published the fixed releases, v7.4.22 and v8.1.10, the same day. Composer refuses versions with a known advisory, so every older release was out at once. The fixed ones were less than a week old, so the cooldown held them back. Between the two rules no version of symfony/ was left, and Laravel could not be resolved at all — for a full week, until the fix was seven days old.
That is not a corner case. It happens after every security release of a package everything depends on, and those are exactly the releases you want fastest. A project with a lock file mostly doesn't notice: its locked version stays, and you can take the fix by name with composer update symfony/. A new project has no lock file. Anyone who bought kitloom that week would have seen their first command fail.
So the starters stay without a cooldown, and the publishing script strips the policy from the copy that goes out.
Your site, your choice
A site that runs composer update regularly is in a different position from a fresh install, and for most of them a cooldown is worth having. The Deployment guide shows the lines to add, and what they cost:
- after a security release,
composer updatecan fail until you take the fix by name; - fixes come a week later unless you take them by name, so watch
composer audit; - Nova is not covered, and kitloom's packages wait a week as well unless you ignore them;
- Composer older than 2.11 ignores the setting without a word, on your machine and in CI;
- a version that hides its harm for longer than the period still gets in.
None of this replaces reading what you update. It narrows the window in which almost every hijacked release so far has been caught, at the price of a command you sometimes have to type by hand.
Try it
Open a sandbox in one click, with no sign-up: Filament or Nova. How updates reach a live kitloom site, with the cooldown and without, is in the Deployment guide.