Composer It is not safe to use packagist and a private package source at the same time

    image
    There was already something similar. Although this behavior was not a bug, but it was fixed. The thing was that composer could install not the package that is specified in composer.json, but its replacement: Composer: Replace, Conflict & Forks Explained , Composer: Downloading Random Code Is Not A Security Vulnerability? . But there remains a different behavior. It is obvious, but, it seems to me, deprived of attention.

    Composer aims to install a more recent version of the package. And he does not care where he finds this package, in a private source of packages or on packagist.

    Thus, if packagist and a private source of packages are used at the same time, then there is a possibility that the private package will be replaced by another of packagist (if they have the same name and, for example, version). Thus, it is likely that the package could be (given Murphy's law, it will) be intentionally replaced by an attacker.

    Conclusion : It is unsafe to use packagist and a private source of packages at the same time.

    If nothing is used with packagist, then you can simply disable it . If you need those and those packages, then it is advisable to create your ecosystem using satis or something like that.

    You can also create an empty package on packagist so that no one can replace yours, but this is not consistent with the main ideas of packagist.

    # 3509

    PS Reproduced simply. It is enough to create a repository on github with compser.json with one commit and a tag that will be higher or equal to the version of your private package. Then add it to packagist.org. After that, upgrade and get the package with packagist, and not from the private repository. An example of such a package. .

    Script to play
    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
    


    PPS The documentation says that packages from own repositories take precedence over packagist packages, but this is true only when the version ('dev-master') is specified as the version, and not the version number (0.0.0).

    PPPS Behavior Changed. Now repositories take precedence and packagist last. github.com/composer/composer/pull/3982

    Also popular now: