Better Ruby Gemfile security: A step-by-step guide using Snyk
Ruby is a well-defined and thought-out language and has been around since the mid-1990s. In 2004, Ruby incorporated RubyGems as its package manager. RubyGems is used to manage libraries and dependencies in a self-contained format known as a gem. The interface for RubyGems is a command line tool that integrates with the Ruby runtime and allows Gemfiles to be added or updated in a project.
I looked at three Ruby platforms and found vulnerabilities that were surprising, even to me. Here’s what to look for if you want better Ruby Gemfile security and what to do if you do find vulnerabilities.
The role of package management
Like other languages, Ruby has a few options when it comes to package management. One of the more widely used for application management is Bundler, which is actually initially installed as a Ruby gem.
A package manager like Bundler can install many gems in a Gemfile, while RubyGems requires one-by-one installation using
gem install. This streamlines Ruby package management when you have a large gem set to maintain or install in an application.
Package managers undoubtedly make life easier when it comes to maintaining libraries and dependencies within an application. However, it’s important to know what you are using and the risks that are potentially surfaced in your stack. Something as simple as a security scan can be done quickly to identify issues that may arise saving time, money, and your end users’ trust down the track.
A look at vulnerabilities
Before we delve into what I found while scanning platforms I’ve used in the past, I want to point out a few things:
- As a user/developer of these platforms, I was surprised at my findings. This reinforces the idea that continually building awareness and education is paramount for developing securely.
- In all the below instances, I reached out to discuss the vulnerabilities with each community and to make sure they were aware of the issues, though many already had fixes.
Spree is one of the more commonly used ecommerce platforms in the Ruby ecosystem. It’s always been one of my ecommerce open source go-to’s. Spree has been around since 2007 and has a large community of developers and companies helping maintain it.
The first step in scanning is to create a
Gemfile.lock manifest which can be scanned using the Snyk CLI tool. After cloning the spree repository and running Bundle install, the lockfile is created with the required Gemfile libraries and dependencies from the Gemfile manifest in the project.
One tip for OSX and brew users with MariaDB installed: MySQL2 gem install might throw an error during the Bundler install process. I had to
brew install openssl first and set the path using
Once the lockfile is created, run
snyk test. Mine returned the following medium vulnerabilities:
Tested 142 dependencies for known issues, found 2 issues, 84 vulnerable paths. Issues with no direct upgrade or patch: ✗ Information Exposure [Medium Severity][https://snyk.io/vuln/SNYK-RUBY-ACTIONCABLE-20338] in firstname.lastname@example.org introduced by email@example.com > firstname.lastname@example.org > email@example.com > firstname.lastname@example.org > email@example.com and 1 other path(s) No upgrade or patch available ✗ Web Cache Poisoning [Medium Severity][https://snyk.io/vuln/SNYK-RUBY-RACK-1061917] in firstname.lastname@example.org introduced by email@example.com > firstname.lastname@example.org and 81 other path(s) No upgrade or patch available
In the above scan there are two issues identified with medium severity.
Information Exposure is introduced via an indirect dependency through a gem called
spree_core. As the name suggests, it can lead to data being remotely retrieved from the core platform.
Web Cache Poisoning is the other vulnerability identified which is brought in via an indirect dependency with a gem called
actionpack. This essentially enables an attacker to trick the server cache into making malicious responses to valid requests. Check out this post on cache poisoning for a more in-depth read.
Sinatra is a lightweight and portable web server. It’s not only one of my favourites for demos and small apps, but it also makes it super fast and easy to get apps up and running really quickly. With over 160 million downloads to date, it’s used far and wide for a variety of projects.
This time I used Bundler to bundle init in a new directory to create a blank Gemfile, then edited the gem file to add
gem 'sinatra' to the bottom of the file. I also added a gem called
erubis, which is a commonly used HTML templating gem that allows for rapid frontend development (and it goes really well with Sinatra).
# frozen_string_literal: true source "https://rubygems.org" gem 'sinatra' gem 'erubis'
Once the Gemfile is saved, install all the required gem dependencies by running
bundler install. After waiting a few seconds the package manager will create a
Gemfile.lock manifest and be ready for a security scan. My scan showed the following:
Tested 7 dependencies for known issues, found 2 issues, 3 vulnerable paths. Issues with no direct upgrade or patch: ✗ Cross-site Scripting (XSS) [Medium Severity][https://snyk.io/vuln/SNYK-RUBY-ERUBIS-20482] in email@example.com introduced by firstname.lastname@example.org No upgrade or patch available ✗ Web Cache Poisoning [Medium Severity][https://snyk.io/vuln/SNYK-RUBY-RACK-1061917] in email@example.com introduced by firstname.lastname@example.org > email@example.com and 1 other path(s) No upgrade or patch available
The erubis gem vulnerability (CWE-79) is one I’ve dug into. The documentation contains an incorrect escaping method that could open the application to an XSS attack. In the erubis documentation, many of the examples use
<%= expr %> which is not escaping stored template variables. To properly escape, and ensure stored HTML elements are not outputting into templates, they need to be escaped like this
<%== expr %>.
As a developer It’s always important to not only scan for vulnerabilities at the code level but also understand the threat as part of development security due diligence.
Ruby on Rails
Rails is one of the most widely used of all the gems in the Ruby ecosystem. With over 293 million total downloads from RubyGems, it is an obvious and popular choice for web application development.
Doing some due diligence using the Snyk Vulnerability Database, I saw a number of versions to be wary of. However, the current version (6.1.4 at time of writing) has no known vulnerabilities.
gem install rails, and then create a blank Rails project by running
rails new myapp. This creates a new blank Rails template to build an app on. Once the libraries and dependencies were setup, I then did a security scan using
snyk test. It found the following vulnerabilities detected in the package manifest.
Tested 72 dependencies for known issues, found 2 issues, 36 vulnerable paths. Issues with no direct upgrade or patch: ✗ Information Exposure [Medium Severity][https://snyk.io/vuln/SNYK-RUBY-ACTIONCABLE-20338] in firstname.lastname@example.org introduced by email@example.com > firstname.lastname@example.org No upgrade or patch available ✗ Web Cache Poisoning [Medium Severity][https://snyk.io/vuln/SNYK-RUBY-RACK-1061917] in email@example.com introduced by firstname.lastname@example.org > email@example.com and 34 other path(s) No upgrade or patch available
Digging into these a bit further I can see that the Action Cable gem, which is a dependency of Rails, has an alert for potential information exposure. This issue seems to have been identified in 2016 with no remediated fix in the core framework library. After a deeper look at the PR listed in the Snyk Vulnerability Database, I found a code-based workaround that instead mitigates the issue. It was suggested in 2019.
The other issue is introduced by the Rack gem and is again around web cache poisoning, the same as the spree commerce issue from above.
Help communities by contributing back
I always love getting hands-on with code, especially digging into identified vulnerabilities and understanding them at the code level after some research.
It only takes a few moments to do a scan and see if there are any known vulnerabilities in the libraries, code, or platforms you are using, and this could save time and keep end users safe. For the unsuspecting developer, team, or company using these platforms in production, they may not be aware what exactly is being let in. Hopefully, this blog helps some teams stay safe.
Remember too that these communities do amazing work in helping build libraries for us all to use so it’s important to contribute back where you can. Even just helping with documentation or testing of a release candidate can help. I’m just one developer and this is just one blog. For us to really make a big security impact, I’d encourage you all to test projects yourself and contribute to the fixes.
Scan your code for free
Find security vulnerabilities in your code, dependencies, containers, and IaC with Snyk.