Pull to refresh

Composer. Небезопасно использовать packagist и приватный источник пакетов одновременно

Reading time3 min
Views6.9K
image
Уже было нечто подобное. Хотя это поведение багом не было, но его исправили. Дело было в том, что 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
Tags:
Hubs:
Total votes 12: ↑9 and ↓3+6
Comments5

Articles