bundle-audit is a command-line utility provided by the bundler-audit ruby gem. It does patch-level vulnerability scans on your Ruby dependencies by working with bundler to inspect your project's Gemfile.lock .

I want to run bundle-audit from a rake task in a Rails project. Here's how I did it.

This is my lib/tasks/bundle_audit.rake file.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 require ' bundler/audit/cli ' namespace :bundle_audit do desc ' Update bundle-audit database ' task :update do Bundler :: Audit :: CLI .new.update end desc ' Check gems for vulns using bundle-audit ' task :check do Bundler :: Audit :: CLI .new.check end desc ' Update vulns database and check gems using bundle-audit ' task :run do Rake :: Task [ ' bundle_audit:update ' ].invoke Rake :: Task [ ' bundle_audit:check ' ].invoke end end task :bundle_audit do Rake :: Task [ ' bundle_audit:run ' ].invoke end

It defines a few rasks under the bundle_audit namespace. Thanks to the modular Ruby code built on top of thor I had no trouble tapping directly into the command-line implementation for bundle-audit .

1 2 3 4 $ rake -T bundle_audit rake bundle_audit:check # Check gems for vulns using bundle-audit rake bundle_audit:run # Update vulns database and check gems using bundle-audit rake bundle_audit:update # Update bundle-audit database

Invocation is as easy as you can imagine. On the command-line:

1 2 3 4 5 6 7 $ rake bundle_audit:run Updating ruby-advisory-db ... From https://github.com/rubysec/ruby-advisory-db * branch master -> FETCH_HEAD Already up-to-date. ruby-advisory-db: 108 advisories No unpatched versions found

As you can see this does two things. First, it updates your local copy of the ruby-advisory-db. Then it scans your gem dependency graph looking for unpatched dependencies. What you see above is the output when everything is OK.

I also incorporated the check into my rake test task, because I want my tests to fail if I'm shipping with vulnerable dependencies. Here's what I have going on in lib/tasks/test.rake :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Rake :: Task [ ' test:all ' ].clear Rake :: Task [ ' test:all:db ' ].clear Rake :: Task [ ' test:db ' ].clear Rake :: Task [ ' test ' ].clear namespace :test do desc ' Run all tests ' task all : :environment do Rake :: Task [ ' bundle_audit ' ].invoke Rake :: Task [ ' brakeman:run ' ].invoke Rake :: Task [ ' rubocop ' ].invoke Rake :: Task [ ' spec ' ].invoke end end task :test do Rake :: Task [ ' test:all ' ].invoke end task default : :test

Since this is part of my testing expectations I can also rest easy because my continuous integration tool has my back on every change, too.