Search
⌘K
    to navigateEnterto select Escto close

    Secure gems with bundle audit

    In this chapter we will learn about discovering and fixing security vulnerabilities in a Rails application. The following content is only for example purposes and needn't be added to granite.

    Time to time people discover security vulnerabilities in published software. Rubysec maintains a plain-text database of such security vulnerabilities.

    ruby-advisory-db maintains a database of vulnerable Ruby Gems.

    If we want to know whether our Ruby application is using any of the versions of Gems that are vulnerable, then we should run a scan of our Gemfile.lock against this database. This is exactly what bundler-audit does.

    bundler-audit is a utility program which looks at an application's Gemfile.lock and then looks at ruby-advisory-db to see if we are using a vulnerable version of Gem or not.

    Installing bundle-audit gem

    Currently, we don't have to install these gems. But if we were to install it, then we would have to add the following lines into our Gemfile:

    1gem 'bundler-audit', require: false
    2gem 'ruby_audit', require: false

    The bundle-audit command which is shown below is only mentioned to illustrate how auditing works. Do not run this command as it might lead to automatic version updates of gems in order to fix the security vulnerabilities that bundle-audit finds. This can further lead to gem version-specific issues throughout the flow of the book.

    Bundler has a command bundle audit to invoke bundler-audit to do this:

    1bundle exec bundle-audit
    2
    3Name: rails-html-sanitizer
    4Version: 1.3.0
    5Advisory: CVE-2015-7580
    6Criticality: Unknown
    7URL: https://groups.google.com/forum/#!topic/rubyonrails-security/uh--W4TDwmI
    8Title: Possible XSS vulnerability in rails-html-sanitizer
    9Solution: upgrade to ~> 1.0.3
    10
    11Vulnerabilities found!

    This scan was run on a project, and we can see that one vulnerability is found.

    Bundler downloads the Ruby Advisory DB to the local machine from time to time. We should always be running the scan against the latest copy of the Ruby Advisory DB.

    To update our local copy of the Ruby Advisory DB, we should execute the following command:

    1bundle audit update
    2
    3Updating ruby-advisory-db ...
    4Cloning into '/Users/raj.singh/.local/share/ruby-advisory-db'...
    5remote: Enumerating objects: 10, done.
    6remote: Counting objects: 100% (10/10), done.
    7remote: Compressing objects: 100% (6/6), done.
    8remote: Total 4863 (delta 4), reused 10 (delta 4), pack-reused 4853
    9Receiving objects: 100% (4863/4863), 867.08 KiB | 3.82 MiB/s, done.
    10Resolving deltas: 100% (2400/2400), done.
    11Updated ruby-advisory-db
    12ruby-advisory-db: 456 advisories

    Note that bundle audit update does not do any audit. It only clones the ruby-advisory-db to the local machine so that next time when we do the audit, it is performed against this update copy.

    Every time we want to do a scan we need to do two things.

    • Update the local Ruby Advisory DB
    • Run the audit

    Both of these operations can be combined to a single command:

    1bundle exec bundle-audit --update

    Running audit as part of CI

    Who is going to run this audit on a regular basis? The best way to do it is to run this audit as a part of CI.

    bundle-audit --update is in our config file for Wheel.

    Let's say that at 10 AM all our tests were passing. Then at 10:05 AM Ruby Advisory DB added a new vulnerability that was recently detected. Any test that runs after 10:05 AM will fail the audit check.

    Here is what we see in the console for a recent run:

    1#!/bin/bash
    2bundle exec bundle-audit check --update --ignore=CVE-2015-9284
    3Updating ruby-advisory-db ...
    4
    5Cloning into '/home/circleci/.local/share/ruby-advisory-db'...
    6
    7Warning: Permanently added the RSA host key for IP address '140.82.113.4' to the list of known hosts.
    8remote: Enumerating objects: 10, done.
    9
    10remote: Counting objects: 100% (10/10), done.
    11
    12remote: Compressing objects: 100% (6/6), done.
    13
    14remote: Total 4863 (delta 4), reused 10 (delta 4), pack-reused 4853
    15
    16Receiving objects: 100% (4863/4863), 865.47 KiB | 21.11 MiB/s, done.
    17
    18Resolving deltas: 100% (2400/2400), done.
    19
    20Updated ruby-advisory-db
    21
    22ruby-advisory-db: 456 advisories
    23
    24Name: actionpack
    25
    26Version: 6.0.3.1
    27
    28Advisory: CVE-2020-8185
    29
    30Criticality: Unknown
    31
    32URL: https://groups.google.com/g/rubyonrails-security/c/pAe9EV8gbM0
    33
    34Title: Untrusted users able to run pending migrations in production
    35
    36Solution: upgrade to >= 6.0.3.2
    37
    38
    39
    40Name: rack
    41
    42Version: 2.2.2
    43
    44Advisory: CVE-2020-8184
    45
    46Criticality: Unknown
    47
    48URL: https://groups.google.com/g/rubyonrails-security/c/OWtmozPH9Ak
    49
    50Title: Percent-encoded cookies can be used to overwrite existing prefixed cookie names
    51
    52Solution: upgrade to ~> 2.1.4, >= 2.2.3
    53
    54
    55
    56Vulnerabilities found!
    57
    58
    59Exited with code exit status 1
    60CircleCI received exit code 1

    In this case two gems actionpack and rack are found to be vulnerable. The solution is also printed in the log:

    1Solution: upgrade to >= 6.0.3.2
    2Solution: upgrade to ~> 2.1.4, >= 2.2.3

    Upgrade the Gems to fix the error.

    There is nothing to commit in this chapter since all we had done was understand the usage of bundler-audit.

    Previous
    Next