Уже было нечто подобное. Хотя это поведение багом не было, но его исправили. Дело было в том, что composer мог установить не тот пакет, который указан в composer.json, а замещающий его: Composer: Replace, Conflict & Forks Explained, Composer: Downloading Random Code Is Not A Security Vulnerability?. Но осталось другое поведение. Оно очевидно, но, как мне кажется, обделено вниманием.
Composer стремится установить более свежую версию пакета. И ему не важно где он найдёт этот пакет, в приватном источнике пакетов или на packagist.
Таким образом, если используются packagist и приватный источник пакетов одновременно, то существует вероятность того, что приватный пакет будет заменен на другой из packagist (если у них совпадут имена и, например, версии). Таким образом существует вероятность того, что пакет может быть(если учесть закон Мерфи, то будет) преднамернно подменён злоумышленником.
Вывод: Небезопасно использовать packagist и приватный источник пакетов одновременно.
Если ничего не используется с packagist, то его можно просто отключить. Если нужны и те, и те пакеты, то желательно создать свою экосистему используя satis или что-нибудь подобное.
А ещё можно на packagist создать пустой пакет, чтобы никто не смог заменить ваш, но это не согласуется с основной идей packagist.
#3509
P.S. Воспроизводится просто. Достаточно создать на github репозиторий с compser.json c одним коммитом и тэгом, который будет выше или равен версии вашего приватного пакета. Потом добавить его на packagist.org. После этого обновиться и получить пакет с packagist, а не с приватного репозитория. Пример такого пакета..
Сценарий для воспроизведения
mkdir /tmp/test cd /tmp/test curl -sS https://getcomposer.org/installer | php mkdir ./substitute_private cd ./substitute_private echo '{"name": "my_substitute/my_substitute", "type": "library", "description": "substitute_private", "license": "LGPL-3.0+"}' > ./composer.json; git init git add . git commit -m 'initial commit' git tag '0.0.0' cd .. mkdir ./application cd ./application echo '{ "name": "my_application/my_application", "type": "application", "description": "Система управления лицевыми счетами", "keywords": [], "license": "LGPL-3.0+", "repositories": [ {"packagist": false}, {"type": "git", "url": "../substitute_private"}], "require":{ "my_substitute/my_substitute": "~0.0" } }' > composer.json ../composer.phar install ../composer.phar update echo '------------> updated from(without packagist)' git --git-dir=./vendor/my_substitute/my_substitute/.git config --get remote.composer.url echo '{ "name": "my_application/my_application", "type": "application", "description": "Система управления лицевыми счетами", "keywords": [], "license": "LGPL-3.0+", "repositories": [ {"type": "git", "url": "../substitute_private"}], "require":{ "my_substitute/my_substitute": "~0.0" } }' > composer.json ../composer.phar update echo '------------> updated from(with packagist)' git --git-dir=./vendor/my_substitute/my_substitute/.git config --get remote.composer.url
P.P.S. В документации сказано, что пакеты из собственных репозиториев имеют приоритет перед пакетами packagist, но это правда только когда в качестве версии указана ветка('dev-master'), а не номер версии(0.0.0).
P.P.P.S. Поведение изменили. Теперь репозитории имеют приоритет и packagist последний. github.com/composer/composer/pull/3982
