Skip to content

Instantly share code, notes, and snippets.

@jdarcy
Created September 1, 2016 13:06
Show Gist options
  • Save jdarcy/984bfea7dd7489ac06973e704affe294 to your computer and use it in GitHub Desktop.
Save jdarcy/984bfea7dd7489ac06973e704affe294 to your computer and use it in GitHub Desktop.
Making curl|bash suck a tiny bit less
The "curl|bash" way of installing software is insecure due to a complete lack of authentication and integrity checking, but it's popular because it's easy for both users and developers. Using HTTPS protects against MITM attacks, but not against attacks on the origin server. The install script can be replaced and nothing will keep users from executing the possibly malicious replacement. What's needed is some sort of signing mechanism, using keys not on the same server as the install script itself. How can we implement this without sacrificing ease of use? How about this? Let's start with something that's easy to explain.
$ curl $URL | validate $URL | bash
Yes, this makes the pipeline 50% longer, but bear with me. What does "validate" do? First, it passes the URL to a secure authentication service, which maps that URL to a GPG key and returns that key to the user. There might be many such services, with varying levels of security and selectable by the user. Once they key is obtained, "validate" simply uses it to check the contents of its input before producing any output. This protects against both MITM attacks and compromise of the origin server. Replacing the install script will just result in a validation failure unless the authentication service is also compromised. How do we make this even simpler? One option is to make "validate" a wrapper around curl instead of a separate program.
$ vcurl $URL | bash
The new "vcurl" is just like the previous "validate" except that it contains the curl invocation within itself instead of requiring a pipe. Obviously the user needs to trust vcurl but it should be a pretty simple and easily auditable piece of software that shouldn't be difficult to get into any OS distribution that already has curl.
This brings us back to a simple two-stage pipeline, only one character more than before. The only downside is that the software author would have to register either their packages or at the very least themselves with one or more authentication services. That's still a heck of a lot easier than having to create full RPM/DEB packages conforming to myriad rules, and seems like a small price to pay for the security advantages.
Don't get me wrong: curl|bash still sucks. Besides the security issues, it also foregoes the other advantages of real packages - dependency checking, standardized handling of multiple platforms or optional features, history/auditing, clean uninstall, and so on. It's a crappy lazy way for developers to do things, but it doesn't have to be a gigantic security hole as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment