Skip to content

Security: elgalu/guides

Security

security.md

layout title previous next
default
Security
/publishing
/patterns

Security practices are being actively discussed. Check back often.

General

Installing a gem allows that gem's code to run in the context of your application. Clearly this has security implications: installing a malicious gem on a server could ultimately result in that server being completely penetrated by the gem's author. Because of this, the security of gem code is a topic of active discussion within the Ruby community.

RubyGems has had the ability to cryptographically sign gems since version 0.8.11. This signing works by using the gem cert command to create a key pair, and then packaging signing data inside the gem itself. The gem install command optionally lets you set a security policy, and you can verify the signing key for a gem before you install it.

However, this method of securing gems is not widely used. It requires a number of manual steps on the part of the developer, and there is no well-established chain of trust for gem signing keys. Discussion of new signing models such as X509 and OpenPGP is going on in the rubygems-trust wiki, the RubyGems-Developers list and in IRC. The goal is to improve (or replace) the signing system so that it is easy for authors and transparent for users.

Using Gems

Install with a trust policy.

  • gem install gemname -P HighSecurity: All dependent gems must be signed and verified.

  • gem install gemname -P MediumSecurity: All signed dependent gems must be verified.

  • bundle --trust-policy MediumSecurity: Same as above, except Bundler only recognizes the long --trust-policy flag, not the short -P.

  • Caveat: Gem certificates are trusted globally, such that adding a cert.pem for one gem automatically trusts all gems signed by that cert.

Verify the checksum, if available

gem fetch gemname -v version
ruby -rdigest/sha2 -e "puts Digest::SHA512.new.hexdigest(File.read('gemname-version.gem'))

Know the risks of being pwned, as described by Benjamin Smith's Hacking with Gems talk

Building Gems

Sign with: gem cert

  1. Create self-signed gem cert

    cd ~/.ssh gem cert --build [email protected] chmod 600 gem-p*

  • use the email address you specify in your gemspecs
  1. Configure gemspec with cert

Add cert public key to your repository

cd /path/to/your/gem
mkdir certs
cp ~/.ssh/gem-public_cert.pem certs/yourhandle.pem
git add certs/yourhandle.pem

Add cert paths to your gemspec

s.cert_chain  = ['certs/yourhandle.pem']
s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
  1. Add your own cert to your approved list, just like anyone else

    gem cert --add certs/yourhandle.pem

  2. Build gem and test that you can install it

    gem build gemname.gemspec gem install gemname-version.gem -P HighSecurity

    or -P MediumSecurity if your gem depends on unsigned gems

  3. Example text for installation documentation

MetricFu is cryptographically signed. To be sure the gem you install hasn't been tampered with:

Add my public key (if you haven't already) as a trusted certificate

gem cert --add <(curl -Ls https://raw.github.com/metricfu/metric_fu/master/certs/bf4.pem)

gem install metric_fu -P MediumSecurity

The MediumSecurity trust profile will verify signed gems, but allow the installation of unsigned dependencies.

This is necessary because not all of MetricFu's dependencies are signed, so we cannot use HighSecurity.


Include checksum of released gems in your repository

require 'digest/sha2'
built_gem_path = 'pkg/gemname-version.gem'
checksum = Digest::SHA512.new.hexdigest(File.read(built_gem_path))
checksum_path = 'checksum/gemname-version.gem.sha512'
File.open(checksum_path, 'w' ) {|f| f.write(checksum) }
# add and commit 'checksum_path'

Not Recommended: OpenPGP signing is not recommended due to lack of support.

For details, see discussion with Grant Olson and Yorick Peterse.

Credits

Several sources were used for content for this guide:

There aren’t any published security advisories