Composer 2.10 Release
We are excited to announce the release of Composer 2.10.0, introducing native malware filtering and consolidated future-proof customizable dependency policy configuration to control the handling of security advisories, abandoned packages, and now malware. Fast detection of malware for packages published on Packagist.org is provided by Aikido.
This release is part of our push for improved supply chain security for Composer & Packagist outlined in our blog post yesterday.
Software Supply Chains Under Attack
Open-source package ecosystems have become an increasingly attractive and common target for supply chain attacks. While typosquatting and dependency confusion attacks have been a concern for years, we are seeing a steady rise in packages that are intentionally malicious. They carry credential stealers, cryptominers, or backdoors often even targeting developer machines rather than production systems. Protection needs to happen earlier than a code review before production deployment, right when a developer first installs a dependency or updates a version of a dependency.
Composer already filters software versions reported as vulnerable on public databases, but security advisories typically cover disclosed vulnerabilities in legitimate packages. The publication processes often take several days. They are not designed to handle rapid responses to packages that are outright malware or individual malware versions published to GitHub repositories through credential theft. Just a few days ago, attackers gained access to a GitHub repository through a developer’s machine and published malware to laravel-lang packages. Two weeks earlier the popular package intercom/intercom-php had malicious releases published on packagist.org by an attacker who similarly gained access to the underlying GitHub repository. Only rapid detection and then quick manual intervention on our side prevented the worst.
In addition to this release announcement we published an in-depth analysis of the current state of supply chain security for Composer & Packagist on our blog yesterday.
Malware Policy
Composer 2.10 introduces a malware policy to enable rapid removal of malicious versions published either by attackers who briefly gained control of a legitimate package, or by maintainers acting in bad faith. Flagged versions are removed from the resolution pool, so they cannot be installed via composer update, composer require or composer create-project. Crucially, the check also runs during composer install where versions flagged after a composer.lock was generated will fail the next install. A malicious release that slipped into a lockfile will not be silently pulled in on CI runs or in production deployments. The same versions are surfaced by composer audit, which fails the audit when finding malware by default.
Thanks to Aikido providing Packagist.org with a CC-BY 4.0 licensed feed of package versions they flagged as malware. The feature is enabled for all Composer users by default and requires no configuration for users installing packages from Packagist.org. Packages with versions flagged as malware are prominently marked on their respective package pages on Packagist.org, so they are easy to identify when browsing.
Private Packagist already supports the new dependency policies for malware, so as a customer you can be sure your applications benefit from the same additional security. Private Packagist Update Review already highlights malware in addition to security advisories. We are working on quickly expanding security monitoring to include malware detection next to handling of security advisories. Malware notifications will be enabled anywhere security advisories are currently enabled. We are going to post additional follow ups over the next few days on new supply chain security functionality in Private Packagist building on this Composer release.

This feature was originally implemented in PR #12766 and consolidated under the new policy configuration in PR #12804, as described in issue #12786.
Default Dependency Policies
The defaults match what most projects want out of the box:
- Malware is blocked during updates, fails audits and is blocked during composer installs to prevent impact on your systems as quickly as possible.
- Package versions with security advisories are blocked during updates and fail audits, but can be installed. You get a chance to evaluate if a published vulnerability affects you before you decide to patch.
- Abandoned packages are only reported by audit but are not blocked during update or install.
Dependency Policy Configuration
Composer 2.10 unifies configuration for the handling of security advisories, abandoned packages, and now versions flagged as malware together under a unified config.policy object. This new configuration supersedes the previous config.audit settings.
Every dependency policy configuration shares the same structure:
blockcontrols if matching package versions are removed from the dependency resolution pool beforecomposer update/require/etc run, and for malware also, whether package versions are available for composer install from an existing lock file,auditcontrols howcomposer audittreats matching package versions (ignore,report, orfail), andignoreprovides per-package exemptions.
Additionally, the advisories policy has the option to exempt issues based on ignore-id, for identifiers like CVE numbers, and ignore-severity and the malware policy allows exemptions through ignore-source.
The malware policy allows you to control whether malware blocking should happen only during composer update (including require, and remove) like for advisories or abandoned packages, or also during composer install with the block-scope option, defaulting to all.
A policy can be turned off individually by setting it to false:
{
"config": {
"policy": {
"abandoned": false
}
}
}Setting "policy": false is the kill switch that disables all policies at once. If you only want to temporarily disable blocking of versions from being considered for dependency resolution or blocking of flagged malware versions during installs, you can use the new --no-blocking flag (or the COMPOSER_NO_BLOCKING environment variable for CI). The flag is available for update, require, remove, create-project, and install (applies to malware only).
Beyond the three built-in dependency policies, organizations can plug in their own. For example, an internally maintained list of package versions disallowed by company policy. Custom policies depend on package version lists either coming from a Composer repository that advertises them, or from one or more explicit HTTPS endpoints configured under sources:
{
"config": {
"policy": {
"company-policy": {
"sources": [
{"type": "url", "url": "https://acme.example.com/bad-pkgs.json"}
],
"audit": "fail"
}
}
}
}For projects already configuring config.audit.*, these keys continue to work as a fallback in 2.10, and an explicit deprecation warning will follow in Composer 2.11. The migration is one-to-one, e.g. audit.block-insecure → policy.advisories.block, audit.ignore-severity → policy.advisories.ignore-severity. See the configuration documentation for the full mapping.
This work shipped over multiple PRs and is tracked in issue #12786. The full policy documentation is available on getcomposer.org: Config.
New Sponsorship Program
In addition to providing their malware analysis data to the PHP ecosystem for free, we would like to thank Aikido for becoming a Composer & Packagist.org financial sponsor! Financial contributions help us pay our staff for operating and supporting Packagist.org, e.g. reacting to supply chain attacks in the middle of the night, and maintaining and building new features for Composer. If your business is also interested in joining this new sponsorship program, please reach out to sponsoring@packagist.org to be included in our launch announcement and new sponsorship website in June!
Deprecating Source Fallback
Together with the new malware controls Composer 2.10 is deprecating source fallback behavior. Composer would previously attempt to install a package from source when an artifact (dist) download fails. This unexpected source checkout can have unintended security implications when installing a package from a private Composer repository. For example, if Private Packagist has mirrored open-source packages, but the network configuration results in a connection failure, a source fallback can result in the installation of a matching tag from the underlying git repository containing malware, when the Private Packagist artifact would have still contained a previous known-good state.
A new source-fallback config option gives you the ability to still enable the legacy source fallback behavior. Composer 2.11 will remove this feature, if you rely on it, please open an issue on our GitHub issue tracker and explain your specific use case. Implementation in PRs #12698 and #12885
Wildcard Support for --with Constraints
The --with flag on composer update allows you to apply a temporary version constraint override, narrowing down the existing constraint, for a single update run without touching your composer.json. In 2.10, the package name in --with now accepts wildcards, making it possible to temporarily narrow constraints across an entire vendor namespace in one go:
composer update --with "acme/*:^2.0"Previously, this required a separate --with argument for every individual package. For projects migrating to a new major version of a framework or SDK with many sub-packages, this is a significant quality-of-life improvement.
This feature was implemented in PR #12658.
Adding Requirements During create-project
The create-project command now accepts a --require parameter to require additional packages in a new project while it is set up:
composer create-project acme/skeleton my-project --require="acme/extra-bundle:^1.0"This eliminates the need for a follow-up composer require step immediately after scaffolding, which is particularly convenient when creating projects programmatically or in automated pipelines.
This feature was implemented in PR #12738.
Other Notable Improvements
--bump-after-updatefix: The flag now only bumps the version constraints of packages that were actually updated, rather than all packages in the lock file. #12733- Plugin autoloading optimized: Classmaps are no longer regenerated for every package per plugin, reducing overhead during install and update operations. #12696
- PoolOptimizer memory usage has been reduced. #12783
Find out about other features and bugfixes in the complete changelog.