From 3ea2ba8567317ae91590869b939b6a09fd13be49 Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Thu, 16 Jul 2015 14:28:38 -0500 Subject: [PATCH] Add brakeman security scanner Run via `script/brakeman` Intentionally runs outside of bundle, per author recommendation Uses brakeman-min since we don't need csv, haml, slim output Caching is enabled per http://docs.travis-ci.com/user/caching/#Enabling-multiple-caching-features --- .travis.yml | 6 ++++- config/brakeman.yml | 10 ++++++++ lib/tasks/brakeman.rake | 57 +++++++++++++++++++++++++++++++++++++++++ reports/.keep | 0 script/brakeman | 5 ++++ 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 config/brakeman.yml create mode 100644 lib/tasks/brakeman.rake create mode 100644 reports/.keep create mode 100755 script/brakeman diff --git a/.travis.yml b/.travis.yml index 48f9f083f20..e7d7aed3f93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,8 @@ language: ruby -cache: bundler +cache: + bundler: true + directories: + - reports rvm: - 2.1.6 @@ -29,6 +32,7 @@ before_script: script: - bundle exec rake - bundle exec rake rubocop + - script/brakeman env: - RUBYGEMS_VERSION=2.4.5 diff --git a/config/brakeman.yml b/config/brakeman.yml new file mode 100644 index 00000000000..cf0f646dc31 --- /dev/null +++ b/config/brakeman.yml @@ -0,0 +1,10 @@ +--- +:min_confidence: 3 +:ignore_ifs: false +:skip_libs: false +:exit_on_warn: false +:interactive_ignore: false +:output_files: +- reports/brakeman.json +- reports/brakeman.html +:rails4: true diff --git a/lib/tasks/brakeman.rake b/lib/tasks/brakeman.rake new file mode 100644 index 00000000000..5e4a58a0798 --- /dev/null +++ b/lib/tasks/brakeman.rake @@ -0,0 +1,57 @@ +# see https://github.com/presidentbeef/brakeman/ +desc 'Run Brakeman security scanner' +task :brakeman do + previous_report = 'reports/old_brakeman.json' + current_report = 'reports/brakeman.json' + if File.readable?(current_report) + mv current_report, previous_report + diff_reports = true + else + diff_reports = false + end + require 'brakeman' + + tracker = Brakeman.run app_path: '.', config_file: 'config/brakeman.yml' + # https://github.com/presidentbeef/brakeman/blob/3.0_branch/lib/brakeman/report/report_table.rb#L42 + Brakeman.load_brakeman_dependency 'terminal-table' + tracker.report.require_report 'base' + custom_report = Class.new(Brakeman::Report::Base) do + def initialize(tracker) + super(tracker.instance_variable_get('@app_tree'), tracker) + end + + def generate + num_warnings = all_warnings.length + + Terminal::Table.new(headings: ['Scanned/Reported', 'Total']) do |t| + t.add_row ['Controllers', tracker.controllers.length] + t.add_row ['Models', tracker.models.length - 1] + t.add_row ['Templates', number_of_templates(@tracker)] + t.add_row ['Errors', tracker.errors.length] + t.add_row ['Security Warnings', "#{num_warnings} (#{warnings_summary[:high_confidence]})"] + t.add_row ['Ignored Warnings', ignored_warnings.length] unless ignored_warnings.empty? + end + end + end + report = custom_report.new(tracker) + STDERR.puts "\033[31mBrakeman Report\033[0m" + STDERR.puts report.generate + # https://github.com/presidentbeef/brakeman/blob/3.0_branch/lib/brakeman.rb + if diff_reports + Brakeman.load_brakeman_dependency 'multi_json' + require 'brakeman/report/initializers/multi_json' + require 'brakeman/differ' + previous_results = MultiJson.load(File.read(previous_report), symbolize_keys: true)[:warnings] + new_results = MultiJson.load(tracker.report.to_json, symbolize_keys: true)[:warnings] + STDERR.puts Brakeman::Differ.new(new_results, previous_results).diff + end + if report.all_warnings.any? + STDERR.puts Terminal::Table.new( + headings: %w(Summary Details), + rows: [ + ["#{report.all_warnings.count} warnings.", + "open 'reports/brakeman.html'"] + ]) + exit Brakeman::Warnings_Found_Exit_Code if tracker.options[:exit_on_warn] + end +end diff --git a/reports/.keep b/reports/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/script/brakeman b/script/brakeman new file mode 100755 index 00000000000..d282ad55430 --- /dev/null +++ b/script/brakeman @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Does not install the latest brakeman if already installed +gem install terminal-table --conservative +gem install brakeman-min --conservative +ruby -rbrakeman -S rake -f lib/tasks/brakeman.rake brakeman