Automate Security Scans with Continuous Integration
There are many tools out there that help you get a quick idea of possible security issues in your code and dependencies, but how often do you run them? If you’re running a Rails app and have never run brakeman or bundler-audit, I strongly urge you to run these tools immediately. Brakeman finds common insecure coding patterns that might be exploitable in the correct context and bundler-audit checks for known vulnerabilities within your installed gem dependencies.
The premise of this blog post isn’t to teach you to run these tools, but rather to teach you how to implement these tools into your Continuous Integration service. If you’re curious of how to run these tools outside of the test suite, both tool’s READMEs are informative.
Rietta currently uses TravisCI in order to automate the running of
brakeman. We also automate
rspec, and many other tools. Recently, when nokogiri CVE-2017-9050 came out, all active projects of Rietta notified via a CRON Travis job that alerted us via email and via slack that our
nokogiri dependency had a vulnerability and needed to be updated.
The fix was simple, adding the following lines in our Gemfile to lock the version of
nokogiri above the exploitable version:
# intentionally locked due to nokogiri CVE-2017-9050 # https://github.com/sparklemotion/nokogiri/issues/1673 gem 'nokogiri', '>= 1.8.1'
The comments are not necessarily needed, but we like to be explicit to ensure this stays locked to keep from accidentally utilizing a vulnerable version of
So how do we do it?
In travis, this configuration is actually quite simple:
language: ruby rvm: - 2.4.1 before_script: # install gems manually to ensure they are installed locally # travis won't have these, so this will install whatever the # latest is for your Ruby version - gem install brakeman - gem install bundle-audit - bundle-audit update # ensure we have the latest vulnerability database script: # don't use bundle exec to use locally installed versions - brakeman -z - bundle-audit
Note that if you want to run your test suite, you’ll need to have your pre-setup in before_script. In Rietta case,
bin/setup does all the heavy lifting of repo setup for us, so we just add
bin/setup to run in the before_script). You’ll also need to add the command you use to run your test suite. By default,
bin/rake should run your test suite.
An example of a more complete
.travis.yml might look like so:
language: ruby rvm: - 2.4.1 cache: bundler addons: postgresql: '9.4' before_script: - bundle exec bin/setup - gem install bundle-audit - bundle-audit update script: - bundle exec bin/rake - bundle exec rubocop - bundle exec brakeman -z - bundle-audit
In addition to having this build on pushes, we also run our CI daily utilizing Travis' CRON feature. This allows us to get a daily check that will alert us if either
As demonstrated, adding security checks to your CI is can be a rather trivial, yet rewarding, feature addition. Rietta would love to hear what your security pipeline includes.