Уже было нечто подобное. Хотя это поведение багом не было, но его исправили. Дело было в том, что 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