---
title: Handling Security Issues In Open Source Projects
teaser: How to handle vulnerabilities in your open source project.
tags: security,open source
author: Tute Costa
published_on: 2014-12-24
---

A [vulnerability was recently discovered in the doorkeeper
gem](http://seclists.org/oss-sec/2014/q4/1076). It taught me the hard way how to
deal with security issues in OSS, and I documented what I’ve learned in the
process.

## Keep it private at first

When you become aware of a vulnerability in a project you maintain, keep it
private. A vulnerability shouldn't be made public until it's been fixed.

Rails developers may have experienced this: a new patch version of Rails is
suddenly announced, and you **should** upgrade. What happens in such cases is:

1. Someone discovers a vulnerability.
2. Rails core team work with the discoverer to fix it.
3. A new patch version is released for affected Rails versions.
4. The vulnerability and how to upgrade is announced in Ruby on Rails Twitter
   account, their blog, security mailing lists, etc.

Let’s see in detail how all this happens.

## Request a CVE identifier

Before you start fixing the bug (or while you are doing it) you should request a
"CVE id". An id can be requested from any of the ["CVE Numbering
Authorities"](https://cve.mitre.org/cve/cna.html). I myself sent my request to
RedHat, and Kurt Seifried provided me with an identifier in less than an hour.
He hosts a [wiki with more
information](https://people.redhat.com/kseifrie/CVE-OpenSource-Request-HOWTO.html).

CVE stands for "Common Vulnerabilities and Exposures". This allows us to sanely
talk about security issues ("issue CVE-2009-3555" instead of "the OpenSSL
vulnerability, from like 2009, the DoS one... no, not that one"). CVE allows
multiple vendors, products, and customers to properly track security
vulnerabilities and make sure they are dealt with. CVE Identifiers are from an
international information security effort that is publicly available and free to
use.

## Write the accompanying CVE report

The <abbr title="Common Vulnerabilities and Exposures">CVE</abbr> report
specifies:

- The project (name and related links)
- A description of the vulnerability
- Affected and fixed versions
- What’s the vulnerability’s impact (how many people are affected and how)
- What is the upgrade process
- What workarounds can users take, if any
- Credits
- Any other kind of relevant information you can provide

Here is my example:

    Cross-site request forgery (CSRF) vulnerability in doorkeeper 1.4.0
    and earlier allows remote attackers to hijack the user's OAuth
    autorization code. This vulnerability has been assigned the CVE
    identifier CVE-2014-8144.

    Versions Affected:  1.4.0 and below
    Fixed Versions:     1.4.1, 2.0.0

    ## Impact

    Doorkeeper's endpoints didn't have CSRF protection. Any HTML document
    on the Internet can then read a user's authorization code with arbitrary
    scope from any Doorkeeper-compatible Rails app you are logged in.

    ## Releases

    The 1.4.1 and 2.0.0 releases are available at
    https://rubygems.org/gems/doorkeeper and
    https://github.com/doorkeeper-gem/doorkeeper.

    ## Upgrade Process

    Upgrade doorkeeper version at least to 1.4.1.

    ## Workarounds

    There are no feasible workarounds for this vulnerability.

    ## Credits

    Thanks to Sergey Belov of DigitalOcean for finding the vulnerability, Phill
    Baker of DigitalOcean for reporting and fixing it, and to Egor Homakov of
    Sakurity.com for raising awareness.

## Fix it and publish releases

Work on the vulnerability in private. Only publish the fixes when you release
new patched versions of your project. This keeps people from learning about the
vulnerability before it’s been fixed, potentially taking advantage from affected
deploys of your software. The goal is to reach most users of your project so
they can upgrade as soon as possible.

If you take too long to release, the attacker might announce it before you have
a fix ready. The person who reported the vulnerability is the “white hat”. There
may already be “black hats” taking advantage of it. CVE reports typically [go
public after 2 weeks since an id was granted to address this
issue](https://people.redhat.com/kseifrie/CVE-OpenSource-Request-HOWTO.html).

## Spread the word

After you get the CVE identifier and report, the fix and releases ready, publish
this information to security lists and to users of your library, as widely as
you’re able to, using any communication techniques available to you.

I was advised to post doorkeeper’s report to the following lists:

- oss-security@lists.openwall.com Mailing list.
- [ruby-security-ann Google
  Group](https://groups.google.com/forum/#!forum/ruby-security-ann).
- [ruby-advisory-db GitHub
  project](https://github.com/rubysec/ruby-advisory-db).

After all is done you can relax. Until next time!

## One thing end users can do

Adding the report to `ruby-advisory-db` is particularly useful for end users.

Ruby developers can use `bundler-audit`, which uses `ruby-advisory-db`, to
automatically alert themselves of security issues.  We made `bundle-audit` a
dependency in all our Rails apps by adding it to
[Suspenders](https://github.com/thoughtbot/suspenders) in version 1.19.0.

Here's how it is set up in our Rails apps:

```ruby
# Gemfile
group :development do
  gem "bundler-audit"
end

# Rakefile
task default: "bundler:audit"

# lib/tasks/bundler_audit.rake
if Rails.env.development? || Rails.env.test?
  require "bundler/audit/cli"

  namespace :bundler do
    task :audit do
      %w(update check).each do |command|
        Bundler::Audit::CLI.start [command]
      end
    end
  end
end
```

We hook the rake task into our default test suite so that we are sure it is run
often.  Running this task in an app using an insecure version of Doorkeeper
would print out something like:

    Name: doorkeeper
    Version: 1.3.0
    Advisory: CVE-2014-8144
    Criticality: Unknown
    URL: https://groups.google.com/forum/#!topic/ruby-security-ann/5_VqJtNc8jw
    Title: Cross-site request forgery (CSRF) vulnerability in doorkeeper 1.4.0
    and earlier.
    Solution: upgrade to ~> 1.4.1, >= 2.0.0

## Things not to do

Don't do what I did with Doorkeeper:

- Tell the person who reports the vulnerability to send a pull request, which is
  public.
- Wait until the next scheduled release to bump the patch version with the fix.

Instead:

- Keep it private, following the guidelines described above, making it public
  only after the fix is released.
- Release the fix as soon as possible.

A week after the Doorkeeper fix, [Egor Homakov raised
awareness](http://homakov.blogspot.com/2014/12/blatant-csrf-in-doorkeeper-most-popular.html),
calling users to upgrade, and myself to finally release. Thank you Egor for your
pat on the back that morning and for the ongoing help you are providing.
