Why one-line installers are a bad idea

There has been a trend in the last while for various bits of useful software to have a one-line shell command recommended as the installation method. The usual form of this is to pipe something like curl or wget to some interpreter, be it bash, php, ruby, or some such. They look like this (taken from RVM’s installation page):

curl -L https://get.rvm.io | bash -s stable --ruby

RVM is by no means the first bit of software to do this–I remember at various stages PEAR, Homebrew, and others suggesting the same thing. This command takes the output of curl and pipes it straight to bash. I have several issues with this.

It gives you no opportunity to inspect the code that you are running

In this example, you are blindly assuming that the code you get from http://get.rvm.io is actually the RVM installer. There is no verification of any form - if, for example, the host has been compromised, the installer might have been replaced with something as simple as an rm -rf ., which would blow away anything in the current directory. Or, indeed, it could any other command that you have permission to run as the current user. It might not even be intentionally malicious–there could just be a bug which has some unexpected side-effect.

There is no way to verify the source of the code

It could be argued that because the code is delivered over HTTPS in this case, there is some verification of the identity of the source. This is not enough, as can be demonstrated by the case above, where the source is compromised. With packaging systems such as dpkg or rpm, there are cryptographic signatures attached to each package. These sign each release of the package in question, and hence there is a trust layer you can use to help decide if you wish to use the package source. Also, it can then flag up when the source may have been compromised.

You can, of course, override the signature verification step in a package manager along the lines of dpkg or rpm or many others that I have not used; however, at that point, you are making the decision to do so yourself and therefore take responsibility for the results.

In the case of PHP’s Composer, which I’ll come back to, Pádraic Brady pointed out that the Composer people are aware of the issue of running arbitrary unsigned code, and a pull request has been filed to fix part of it. Although I agree with many of the changes made, I don’t believe it does anything to protect the installer itself. (I may be wrong here–if I have misread, please let me know.)

It teaches bad habits

The example that prompted this blog post is that of the PHP utility, Composer. This is a wonderful piece of software for managing library dependencies within PHP projects. However, on their download page, they have two variants of the one-line installer, the first being along the pattern already discussed:

curl -s https://getcomposer.org/installer | php

And the second, for “if you don’t have curl”:

php -r "eval('?>'.
file_get_contents('https://getcomposer.org/installer'));"

In the former case, you are teaching your users that piping code downloaded from web sites directly to an interpreter is OK; in the latter example, you are teaching people that doing the same with eval in PHP is also just fine. I, personally, think this is the worst part of all–while running curl to get the code is bad, it might also end up suggesting to people that eval is just fine for this purpose, when even the most rudimentary material on security will say just the opposite. Software written in PHP has a bad enough reputation for careless use of its capability to open, and if you’re not careful, execute ‘files’ across the Web, and advocating this as part of an installation process is really not a good thing.

In summary

Although installers like this are undoubtedly convenient for the user, there is a huge risk as a result. Convenience and security undoubtedly do not go hand in hand; in this case, it would be far better to encourage people to download the installer file, and then perhaps verify it using a checksum such as SHA256–although, of course, this is also open to compromise, it would be a start. The package could also be signed with GPG or a similar system. This would take the user a few minutes, which undoubtedly gets in the way of using the software in question. However, I believe in this case the loss of convenience is far outweighed by mitigating the security risks involved.