Ruby distros, RubyGems, and SSL—Oy vey!
If you try
gem install and get an error like this:
ERROR: While executing gem ... (OpenSSL::X509::StoreError)
Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://rubygems.org/latest_specs.4.8.gz)
then read on.
(Note: the solutions given here are derived from a Gist written by Luis Lavena, and updated based on my own testing and experiments.)
A quick fix (that doesn’t always work)
On some systems you can fix this problem by dropping a newer certificate into the
rubygems/ssl_certs directory. That will work on many systems, but not all. I have verified that this works on OS X Mavericks (10.9.5) and Windows 8.1 Update. It did not work on Windows 10.1 But it is the fastest and simplest fix and worth a try.
To add the updated certificate to your rubygems installation, download2 the latest certificate—AddTrustExternalCARoot-2048.pem—and place it in this relative directory in your Ruby installation:
lib\ruby\x.x.x\rubygems\ssl_certs. For later versions of Ruby (e.g. 2.2.3) there will be an existing
AddTrustExternalCARoot-2048.pem file; just overwrite it with the downloaded version.
After storing the new certificate, try
gem install again. If it succeeds, you are done!
gem install still fails with some kind of SSL error then you will need to the less quick solution—updating RubyGems to a more recent patch.
The slower fix (that always works)
The fix is to update the RubyGems software within your Ruby installation. I say it always works, but I haven’t tested every Ruby distribution on every OS. But because this fix updates both the RubyGems software (addressing protocol concerns) and the certificate (addressing signature algorithm concerns) I think it is likely to work in all cases.
There is a nice gem to update RubyGems; it is called, oddly enough, rubygems-update. You’ll need to download the appropriate version of that gem, install it, and run it.
gem -vto find the version of RubyGems you have. You are interested in the major and minor version, which are the first two tokens. For example, if
gem -vreports “126.96.36.199” then you care about the leading “2.4”; if the reported version is “1.8.14” then you care about the leading “1.8”.
Now go to https://rubygems.org/gems/rubygems-update/versions and look for the rubygems-update that has the first two tokens matching your RubyGem version and the largest third token. For example, my
gem -vreported “1.8.14”; when I look today for a rubygems-update for “1.8” I see a 1.8.14 there, but the latest (largest) is 1.8.30, so that’s the one I want.
Click the link for the rubygems-update version you want. That will take you to a page discussing that version of RubyGems. On the right side of the page there is sidebar that has a list of links. Click the “Download” link and save the gem file somewhere accessible to your command line.
Install the gem using
gem install --local ~\where-I-saved-it\rubygems-update-1.8.30.gem. (Obviously, your path and gem file name will vary to match your situation.)
Update RubyGems using the command
update_rubygems. Then try
gem -vagain to see that the RubyGems version is updated to the version expected.3
Uninstall rubygems-update using the command
gem uninstall rubygems-update -x
Try installing a gem. If it succeeds, you are done!
Note: If you are still getting some kind of SSL or certificate error, then you will need to also install the latest certificate. See the quick fix for instructions to do that.
Why is this happening to me?!
This is happening because vulnerabilities have been discovered in the SSL and TLS protocols used to make secure network connections. Wikipedia has a nice run down of SSL/TLS vulnerabilities.
The mitigation for these vulnerabilities is in some cases to deprecate the version of the SSL or TLS protocol that has the vulnerability, in some cases to restrict the set of cryptographic algorithms available to secure the connection, and in some cases to change the signing algorithm and key length of the certificates provided by the server and client.
The Ruby distros that most folks use to install Ruby have already been baked; for the most part they don’t get patched and reissued. So those distros will contain whichever version of RubyGems was the latest stable version at the time the distro was created. Which means that you’ll need to update RubyGems yourself after installing just about any Ruby distribution.
Special note about Ruby virtual environments
If you use rbenv or rvm, or if you have been following the advice in my series on automating virtual environments, then you will have a core Ruby installation (one for each version of Ruby you use). That updated RubyGems will be seen automatically by every virtual environment referencing that version of Ruby. Nice.
Except on Windows systems we don’t have rbenv or rvm, not really, and so each virtual environment instance has its own complete copy of Ruby. If you use my method (see posts listed below) to establish Ruby virtual environments on Windows, then after updating the core/reference Ruby installation, you’ll need to either delete the
.rblcl folder and rerun
provision-venv.ps1, or you’ll need to upgrade RubyGems in the existing
It failed for me on Windows 10 on 7 April 2016. This is probably due to Windows 10 being much more strict about TLS and SSL protocols, something that can’t be resolve by a certificate change alone. It is possible that OS X 10.11.4 (El Capitan) would also be strict, but I haven’t had a chance to test that. ↩
Make sure the file is saved with the extension
.pem, not some other extension like
If your Ruby is installed in a directory path that contains spaces (e.g. “C:\Program Files”), then you’ll first need to move the Ruby installation to a location that won’t have a file path containing embedded spaces. After you upgrade RubyGems you can move Ruby back to where you had it. This is some kind of bug in the updater gem, or some kind of bug in Ruby or RubyGems; one that I don’t feel like tracking down. ↩